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 unsigned int smb_echo_count = 0;
34 extern uint32 global_client_caps;
36 extern struct current_user current_user;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
49 const char *s = srcname;
50 NTSTATUS ret = NT_STATUS_OK;
51 BOOL start_of_name_component = True;
52 unsigned int num_bad_components = 0;
55 if (IS_DIRECTORY_SEP(*s)) {
57 * Safe to assume is not the second part of a mb char as this is handled below.
59 /* Eat multiple '/' or '\\' */
60 while (IS_DIRECTORY_SEP(*s)) {
63 if ((d != destname) && (*s != '\0')) {
64 /* We only care about non-leading or trailing '/' or '\\' */
68 start_of_name_component = True;
72 if (start_of_name_component) {
73 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
74 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
77 * No mb char starts with '.' so we're safe checking the directory separator here.
80 /* If we just added a '/' - delete it */
81 if ((d > destname) && (*(d-1) == '/')) {
86 /* Are we at the start ? Can't go back further if so. */
88 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
91 /* Go back one level... */
92 /* We know this is safe as '/' cannot be part of a mb sequence. */
93 /* NOTE - if this assumption is invalid we are not in good shape... */
94 /* Decrement d first as d points to the *next* char to write into. */
95 for (d--; d > destname; d--) {
99 s += 2; /* Else go past the .. */
100 /* We're still at the start of a name component, just the previous one. */
102 if (num_bad_components) {
103 /* Hmmm. Should we only decrement the bad_components if
104 we're removing a bad component ? Need to check this. JRA. */
105 num_bad_components--;
110 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
111 /* Component of pathname can't be "." only. */
112 ret = NT_STATUS_OBJECT_NAME_INVALID;
113 num_bad_components++;
121 return NT_STATUS_OBJECT_NAME_INVALID;
129 return NT_STATUS_OBJECT_NAME_INVALID;
135 switch(next_mb_char_size(s)) {
146 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
148 return NT_STATUS_INVALID_PARAMETER;
151 if (start_of_name_component && num_bad_components) {
152 num_bad_components++;
154 start_of_name_component = False;
157 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
158 if (num_bad_components > 1) {
159 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
167 /****************************************************************************
168 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
169 path or anything including wildcards.
170 We're assuming here that '/' is not the second byte in any multibyte char
171 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
173 ****************************************************************************/
175 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
178 const char *s = srcname;
179 NTSTATUS ret = NT_STATUS_OK;
180 BOOL start_of_name_component = True;
181 unsigned int num_bad_components = 0;
183 *p_contains_wcard = False;
186 if (IS_DIRECTORY_SEP(*s)) {
188 * Safe to assume is not the second part of a mb char as this is handled below.
190 /* Eat multiple '/' or '\\' */
191 while (IS_DIRECTORY_SEP(*s)) {
194 if ((d != destname) && (*s != '\0')) {
195 /* We only care about non-leading or trailing '/' or '\\' */
199 start_of_name_component = True;
203 if (start_of_name_component) {
204 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
205 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
208 * No mb char starts with '.' so we're safe checking the directory separator here.
211 /* If we just added a '/' - delete it */
212 if ((d > destname) && (*(d-1) == '/')) {
217 /* Are we at the start ? Can't go back further if so. */
219 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
222 /* Go back one level... */
223 /* We know this is safe as '/' cannot be part of a mb sequence. */
224 /* NOTE - if this assumption is invalid we are not in good shape... */
225 /* Decrement d first as d points to the *next* char to write into. */
226 for (d--; d > destname; d--) {
230 s += 2; /* Else go past the .. */
231 /* We're still at the start of a name component, just the previous one. */
233 if (num_bad_components) {
234 /* Hmmm. Should we only decrement the bad_components if
235 we're removing a bad component ? Need to check this. JRA. */
236 num_bad_components--;
241 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
242 /* Component of pathname can't be "." only. */
243 ret = NT_STATUS_OBJECT_NAME_INVALID;
244 num_bad_components++;
252 return NT_STATUS_OBJECT_NAME_INVALID;
254 if (!*p_contains_wcard) {
261 *p_contains_wcard = True;
269 switch(next_mb_char_size(s)) {
283 DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
285 return NT_STATUS_INVALID_PARAMETER;
288 if (start_of_name_component && num_bad_components) {
289 num_bad_components++;
291 start_of_name_component = False;
294 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
295 /* For some strange reason being called from findfirst changes
296 the num_components number to cause the error return to change. JRA. */
297 if (num_bad_components > 2) {
298 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
306 /****************************************************************************
307 Check the path for a POSIX client.
308 We're assuming here that '/' is not the second byte in any multibyte char
309 set (a safe assumption).
310 ****************************************************************************/
312 NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
315 const char *s = srcname;
316 NTSTATUS ret = NT_STATUS_OK;
317 BOOL start_of_name_component = True;
322 * Safe to assume is not the second part of a mb char as this is handled below.
324 /* Eat multiple '/' or '\\' */
328 if ((d != destname) && (*s != '\0')) {
329 /* We only care about non-leading or trailing '/' */
333 start_of_name_component = True;
337 if (start_of_name_component) {
338 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
339 /* Uh oh - "/../" or "/..\0" ! */
342 * No mb char starts with '.' so we're safe checking the directory separator here.
345 /* If we just added a '/' - delete it */
346 if ((d > destname) && (*(d-1) == '/')) {
351 /* Are we at the start ? Can't go back further if so. */
353 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
356 /* Go back one level... */
357 /* We know this is safe as '/' cannot be part of a mb sequence. */
358 /* NOTE - if this assumption is invalid we are not in good shape... */
359 /* Decrement d first as d points to the *next* char to write into. */
360 for (d--; d > destname; d--) {
364 s += 2; /* Else go past the .. */
367 } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
377 switch(next_mb_char_size(s)) {
391 DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
393 return NT_STATUS_INVALID_PARAMETER;
396 start_of_name_component = False;
403 /****************************************************************************
404 Pull a string and check the path allowing a wilcard - provide for error return.
405 ****************************************************************************/
407 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
408 NTSTATUS *err, BOOL *contains_wcard)
411 char *tmppath_ptr = tmppath;
414 SMB_ASSERT(dest_len == sizeof(pstring));
418 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
420 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
423 *contains_wcard = False;
425 if (lp_posix_pathnames()) {
426 *err = check_path_syntax_posix(dest, tmppath);
428 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
434 /****************************************************************************
435 Pull a string and check the path - provide for error return.
436 ****************************************************************************/
438 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
441 char *tmppath_ptr = tmppath;
444 SMB_ASSERT(dest_len == sizeof(pstring));
448 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
450 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
452 if (lp_posix_pathnames()) {
453 *err = check_path_syntax_posix(dest, tmppath);
455 *err = check_path_syntax(dest, tmppath);
461 /****************************************************************************
462 Reply to a special message.
463 ****************************************************************************/
465 int reply_special(char *inbuf,char *outbuf)
468 int msg_type = CVAL(inbuf,0);
469 int msg_flags = CVAL(inbuf,1);
473 static BOOL already_got_session = False;
477 memset(outbuf,'\0',smb_size);
479 smb_setlen(outbuf,0);
482 case 0x81: /* session request */
484 if (already_got_session) {
485 exit_server("multiple session request not permitted");
488 SCVAL(outbuf,0,0x82);
490 if (name_len(inbuf+4) > 50 ||
491 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
492 DEBUG(0,("Invalid name length in session request\n"));
495 name_extract(inbuf,4,name1);
496 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
497 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
500 set_local_machine_name(name1, True);
501 set_remote_machine_name(name2, True);
503 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
504 get_local_machine_name(), get_remote_machine_name(),
507 if (name_type == 'R') {
508 /* We are being asked for a pathworks session ---
510 SCVAL(outbuf, 0,0x83);
514 /* only add the client's machine name to the list
515 of possibly valid usernames if we are operating
516 in share mode security */
517 if (lp_security() == SEC_SHARE) {
518 add_session_user(get_remote_machine_name());
521 reload_services(True);
524 already_got_session = True;
527 case 0x89: /* session keepalive request
528 (some old clients produce this?) */
529 SCVAL(outbuf,0,SMBkeepalive);
533 case 0x82: /* positive session response */
534 case 0x83: /* negative session response */
535 case 0x84: /* retarget session response */
536 DEBUG(0,("Unexpected session response\n"));
539 case SMBkeepalive: /* session keepalive */
544 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
545 msg_type, msg_flags));
550 /****************************************************************************
552 conn POINTER CAN BE NULL HERE !
553 ****************************************************************************/
555 int reply_tcon(connection_struct *conn,
556 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
563 uint16 vuid = SVAL(inbuf,smb_uid);
567 DATA_BLOB password_blob;
569 START_PROFILE(SMBtcon);
571 *service_buf = *password = *dev = 0;
573 p = smb_buf(inbuf)+1;
574 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
575 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
577 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
579 p = strrchr_m(service_buf,'\\');
583 service = service_buf;
586 password_blob = data_blob(password, pwlen+1);
588 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
590 data_blob_clear_free(&password_blob);
593 END_PROFILE(SMBtcon);
594 return ERROR_NT(nt_status);
597 outsize = set_message(outbuf,2,0,True);
598 SSVAL(outbuf,smb_vwv0,max_recv);
599 SSVAL(outbuf,smb_vwv1,conn->cnum);
600 SSVAL(outbuf,smb_tid,conn->cnum);
602 DEBUG(3,("tcon service=%s cnum=%d\n",
603 service, conn->cnum));
605 END_PROFILE(SMBtcon);
609 /****************************************************************************
610 Reply to a tcon and X.
611 conn POINTER CAN BE NULL HERE !
612 ****************************************************************************/
614 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
619 /* what the cleint thinks the device is */
620 fstring client_devicetype;
621 /* what the server tells the client the share represents */
622 const char *server_devicetype;
624 uint16 vuid = SVAL(inbuf,smb_uid);
625 int passlen = SVAL(inbuf,smb_vwv3);
629 START_PROFILE(SMBtconX);
631 *service = *client_devicetype = 0;
633 /* we might have to close an old one */
634 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
635 close_cnum(conn,vuid);
638 if (passlen > MAX_PASS_LEN) {
639 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
642 if (global_encrypted_passwords_negotiated) {
643 password = data_blob(smb_buf(inbuf),passlen);
645 password = data_blob(smb_buf(inbuf),passlen+1);
646 /* Ensure correct termination */
647 password.data[passlen]=0;
650 p = smb_buf(inbuf) + passlen;
651 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
654 * the service name can be either: \\server\share
655 * or share directly like on the DELL PowerVault 705
658 q = strchr_m(path+2,'\\');
660 END_PROFILE(SMBtconX);
661 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
663 fstrcpy(service,q+1);
666 fstrcpy(service,path);
668 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
670 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
672 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
674 data_blob_clear_free(&password);
677 END_PROFILE(SMBtconX);
678 return ERROR_NT(nt_status);
682 server_devicetype = "IPC";
683 else if ( IS_PRINT(conn) )
684 server_devicetype = "LPT1:";
686 server_devicetype = "A:";
688 if (Protocol < PROTOCOL_NT1) {
689 set_message(outbuf,2,0,True);
691 p += srvstr_push(outbuf, p, server_devicetype, -1,
692 STR_TERMINATE|STR_ASCII);
693 set_message_end(outbuf,p);
695 /* NT sets the fstype of IPC$ to the null string */
696 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
698 set_message(outbuf,3,0,True);
701 p += srvstr_push(outbuf, p, server_devicetype, -1,
702 STR_TERMINATE|STR_ASCII);
703 p += srvstr_push(outbuf, p, fstype, -1,
706 set_message_end(outbuf,p);
708 /* what does setting this bit do? It is set by NT4 and
709 may affect the ability to autorun mounted cdroms */
710 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
711 (lp_csc_policy(SNUM(conn)) << 2));
713 init_dfsroot(conn, inbuf, outbuf);
717 DEBUG(3,("tconX service=%s \n",
720 /* set the incoming and outgoing tid to the just created one */
721 SSVAL(inbuf,smb_tid,conn->cnum);
722 SSVAL(outbuf,smb_tid,conn->cnum);
724 END_PROFILE(SMBtconX);
725 return chain_reply(inbuf,outbuf,length,bufsize);
728 /****************************************************************************
729 Reply to an unknown type.
730 ****************************************************************************/
732 int reply_unknown(char *inbuf,char *outbuf)
735 type = CVAL(inbuf,smb_com);
737 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
738 smb_fn_name(type), type, type));
740 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
743 /****************************************************************************
745 conn POINTER CAN BE NULL HERE !
746 ****************************************************************************/
748 int reply_ioctl(connection_struct *conn,
749 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
751 uint16 device = SVAL(inbuf,smb_vwv1);
752 uint16 function = SVAL(inbuf,smb_vwv2);
753 uint32 ioctl_code = (device << 16) + function;
754 int replysize, outsize;
756 START_PROFILE(SMBioctl);
758 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
760 switch (ioctl_code) {
761 case IOCTL_QUERY_JOB_INFO:
765 END_PROFILE(SMBioctl);
766 return(ERROR_DOS(ERRSRV,ERRnosupport));
769 outsize = set_message(outbuf,8,replysize+1,True);
770 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
771 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
772 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
773 p = smb_buf(outbuf) + 1; /* Allow for alignment */
775 switch (ioctl_code) {
776 case IOCTL_QUERY_JOB_INFO:
778 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
780 END_PROFILE(SMBioctl);
781 return(UNIXERROR(ERRDOS,ERRbadfid));
783 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
784 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
786 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
792 END_PROFILE(SMBioctl);
796 /****************************************************************************
798 ****************************************************************************/
800 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
805 BOOL bad_path = False;
806 SMB_STRUCT_STAT sbuf;
809 START_PROFILE(SMBchkpth);
811 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
812 if (!NT_STATUS_IS_OK(status)) {
813 END_PROFILE(SMBchkpth);
815 /* Strange DOS error code semantics only for chkpth... */
816 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
817 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
818 /* We need to map to ERRbadpath */
819 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
822 return ERROR_NT(status);
825 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
827 unix_convert(name,conn,0,&bad_path,&sbuf);
829 END_PROFILE(SMBchkpth);
830 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
833 if (check_name(name,conn)) {
834 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
835 if (!(ok = S_ISDIR(sbuf.st_mode))) {
836 END_PROFILE(SMBchkpth);
837 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
842 /* We special case this - as when a Windows machine
843 is parsing a path is steps through the components
844 one at a time - if a component fails it expects
845 ERRbadpath, not ERRbadfile.
847 if(errno == ENOENT) {
849 * Windows returns different error codes if
850 * the parent directory is valid but not the
851 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
852 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
853 * if the path is invalid. This is different from set_bad_path_error()
854 * in the non-NT error case.
856 END_PROFILE(SMBchkpth);
857 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
860 END_PROFILE(SMBchkpth);
861 return(UNIXERROR(ERRDOS,ERRbadpath));
864 outsize = set_message(outbuf,0,0,False);
865 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
867 END_PROFILE(SMBchkpth);
871 /****************************************************************************
873 ****************************************************************************/
875 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
879 SMB_STRUCT_STAT sbuf;
884 BOOL bad_path = False;
888 START_PROFILE(SMBgetatr);
890 p = smb_buf(inbuf) + 1;
891 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
892 if (!NT_STATUS_IS_OK(status)) {
893 END_PROFILE(SMBgetatr);
894 return ERROR_NT(status);
897 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
899 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
900 under WfWg - weird! */
902 mode = aHIDDEN | aDIR;
903 if (!CAN_WRITE(conn))
909 unix_convert(fname,conn,0,&bad_path,&sbuf);
911 END_PROFILE(SMBgetatr);
912 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
914 if (check_name(fname,conn)) {
915 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
916 mode = dos_mode(conn,fname,&sbuf);
918 mtime = sbuf.st_mtime;
923 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
929 END_PROFILE(SMBgetatr);
930 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
933 outsize = set_message(outbuf,10,0,True);
935 SSVAL(outbuf,smb_vwv0,mode);
936 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
937 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
939 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
941 SIVAL(outbuf,smb_vwv3,(uint32)size);
943 if (Protocol >= PROTOCOL_NT1) {
944 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
947 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
949 END_PROFILE(SMBgetatr);
953 /****************************************************************************
955 ****************************************************************************/
957 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
964 SMB_STRUCT_STAT sbuf;
965 BOOL bad_path = False;
969 START_PROFILE(SMBsetatr);
971 p = smb_buf(inbuf) + 1;
972 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
973 if (!NT_STATUS_IS_OK(status)) {
974 END_PROFILE(SMBsetatr);
975 return ERROR_NT(status);
978 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
980 unix_convert(fname,conn,0,&bad_path,&sbuf);
982 END_PROFILE(SMBsetatr);
983 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
986 mode = SVAL(inbuf,smb_vwv0);
987 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
989 if (mode != FILE_ATTRIBUTE_NORMAL) {
990 if (VALID_STAT_OF_DIR(sbuf))
995 if (check_name(fname,conn)) {
996 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
1003 ok = set_filetime(conn,fname,mtime);
1006 END_PROFILE(SMBsetatr);
1007 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1010 outsize = set_message(outbuf,0,0,False);
1012 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1014 END_PROFILE(SMBsetatr);
1018 /****************************************************************************
1020 ****************************************************************************/
1022 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1025 SMB_BIG_UINT dfree,dsize,bsize;
1026 START_PROFILE(SMBdskattr);
1028 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1029 END_PROFILE(SMBdskattr);
1030 return(UNIXERROR(ERRHRD,ERRgeneral));
1033 outsize = set_message(outbuf,5,0,True);
1035 if (Protocol <= PROTOCOL_LANMAN2) {
1036 double total_space, free_space;
1037 /* we need to scale this to a number that DOS6 can handle. We
1038 use floating point so we can handle large drives on systems
1039 that don't have 64 bit integers
1041 we end up displaying a maximum of 2G to DOS systems
1043 total_space = dsize * (double)bsize;
1044 free_space = dfree * (double)bsize;
1046 dsize = (total_space+63*512) / (64*512);
1047 dfree = (free_space+63*512) / (64*512);
1049 if (dsize > 0xFFFF) dsize = 0xFFFF;
1050 if (dfree > 0xFFFF) dfree = 0xFFFF;
1052 SSVAL(outbuf,smb_vwv0,dsize);
1053 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1054 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1055 SSVAL(outbuf,smb_vwv3,dfree);
1057 SSVAL(outbuf,smb_vwv0,dsize);
1058 SSVAL(outbuf,smb_vwv1,bsize/512);
1059 SSVAL(outbuf,smb_vwv2,512);
1060 SSVAL(outbuf,smb_vwv3,dfree);
1063 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1065 END_PROFILE(SMBdskattr);
1069 /****************************************************************************
1071 Can be called from SMBsearch, SMBffirst or SMBfunique.
1072 ****************************************************************************/
1074 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1084 unsigned int numentries = 0;
1085 unsigned int maxentries = 0;
1086 BOOL finished = False;
1093 BOOL check_descend = False;
1094 BOOL expect_close = False;
1095 BOOL can_open = True;
1096 BOOL bad_path = False;
1098 BOOL mask_contains_wcard = False;
1099 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1101 START_PROFILE(SMBsearch);
1103 if (lp_posix_pathnames()) {
1104 END_PROFILE(SMBsearch);
1105 return reply_unknown(inbuf, outbuf);
1108 *mask = *directory = *fname = 0;
1110 /* If we were called as SMBffirst then we must expect close. */
1111 if(CVAL(inbuf,smb_com) == SMBffirst)
1112 expect_close = True;
1114 outsize = set_message(outbuf,1,3,True);
1115 maxentries = SVAL(inbuf,smb_vwv0);
1116 dirtype = SVAL(inbuf,smb_vwv1);
1117 p = smb_buf(inbuf) + 1;
1118 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1119 if (!NT_STATUS_IS_OK(nt_status)) {
1120 END_PROFILE(SMBsearch);
1121 return ERROR_NT(nt_status);
1124 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
1127 status_len = SVAL(p, 0);
1130 /* dirtype &= ~aDIR; */
1132 if (status_len == 0) {
1133 SMB_STRUCT_STAT sbuf;
1136 pstrcpy(directory,path);
1138 unix_convert(directory,conn,0,&bad_path,&sbuf);
1141 if (!check_name(directory,conn))
1144 p = strrchr_m(dir2,'/');
1153 p = strrchr_m(directory,'/');
1159 if (strlen(directory) == 0)
1160 pstrcpy(directory,".");
1161 memset((char *)status,'\0',21);
1162 SCVAL(status,0,(dirtype & 0x1F));
1166 memcpy(status,p,21);
1167 status_dirtype = CVAL(status,0) & 0x1F;
1168 if (status_dirtype != (dirtype & 0x1F))
1169 dirtype = status_dirtype;
1171 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1174 string_set(&conn->dirpath,dptr_path(dptr_num));
1175 pstrcpy(mask, dptr_wcard(dptr_num));
1179 p = smb_buf(outbuf) + 3;
1182 if (status_len == 0) {
1183 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1185 if(dptr_num == -2) {
1186 END_PROFILE(SMBsearch);
1187 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1189 END_PROFILE(SMBsearch);
1190 return ERROR_DOS(ERRDOS,ERRnofids);
1193 dirtype = dptr_attr(dptr_num);
1196 DEBUG(4,("dptr_num is %d\n",dptr_num));
1199 if ((dirtype&0x1F) == aVOLID) {
1200 memcpy(p,status,21);
1201 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1202 0,aVOLID,0,!allow_long_path_components);
1203 dptr_fill(p+12,dptr_num);
1204 if (dptr_zero(p+12) && (status_len==0))
1208 p += DIR_STRUCT_SIZE;
1211 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1213 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1214 conn->dirpath,lp_dontdescend(SNUM(conn))));
1215 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1216 check_descend = True;
1218 for (i=numentries;(i<maxentries) && !finished;i++) {
1219 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1221 memcpy(p,status,21);
1222 make_dir_struct(p,mask,fname,size, mode,date,
1223 !allow_long_path_components);
1224 if (!dptr_fill(p+12,dptr_num)) {
1228 p += DIR_STRUCT_SIZE;
1238 /* If we were called as SMBffirst with smb_search_id == NULL
1239 and no entries were found then return error and close dirptr
1242 if (numentries == 0 || !ok) {
1243 dptr_close(&dptr_num);
1244 } else if(ok && expect_close && status_len == 0) {
1245 /* Close the dptr - we know it's gone */
1246 dptr_close(&dptr_num);
1249 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1250 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1251 dptr_close(&dptr_num);
1254 if ((numentries == 0) && !mask_contains_wcard) {
1255 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1258 SSVAL(outbuf,smb_vwv0,numentries);
1259 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1260 SCVAL(smb_buf(outbuf),0,5);
1261 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1263 /* The replies here are never long name. */
1264 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1265 if (!allow_long_path_components) {
1266 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1269 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1270 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1272 outsize += DIR_STRUCT_SIZE*numentries;
1273 smb_setlen(outbuf,outsize - 4);
1275 if ((! *directory) && dptr_path(dptr_num))
1276 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1278 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1279 smb_fn_name(CVAL(inbuf,smb_com)),
1280 mask, directory, dirtype, numentries, maxentries ) );
1282 END_PROFILE(SMBsearch);
1286 /****************************************************************************
1287 Reply to a fclose (stop directory search).
1288 ****************************************************************************/
1290 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1299 BOOL path_contains_wcard = False;
1301 START_PROFILE(SMBfclose);
1303 if (lp_posix_pathnames()) {
1304 END_PROFILE(SMBfclose);
1305 return reply_unknown(inbuf, outbuf);
1308 outsize = set_message(outbuf,1,0,True);
1309 p = smb_buf(inbuf) + 1;
1310 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1311 if (!NT_STATUS_IS_OK(err)) {
1312 END_PROFILE(SMBfclose);
1313 return ERROR_NT(err);
1316 status_len = SVAL(p,0);
1319 if (status_len == 0) {
1320 END_PROFILE(SMBfclose);
1321 return ERROR_DOS(ERRSRV,ERRsrverror);
1324 memcpy(status,p,21);
1326 if(dptr_fetch(status+12,&dptr_num)) {
1327 /* Close the dptr - we know it's gone */
1328 dptr_close(&dptr_num);
1331 SSVAL(outbuf,smb_vwv0,0);
1333 DEBUG(3,("search close\n"));
1335 END_PROFILE(SMBfclose);
1339 /****************************************************************************
1341 ****************************************************************************/
1343 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1351 SMB_STRUCT_STAT sbuf;
1352 BOOL bad_path = False;
1354 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1356 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1359 uint32 create_disposition;
1360 uint32 create_options = 0;
1362 START_PROFILE(SMBopen);
1364 deny_mode = SVAL(inbuf,smb_vwv0);
1366 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1367 if (!NT_STATUS_IS_OK(status)) {
1368 END_PROFILE(SMBopen);
1369 return ERROR_NT(status);
1372 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1374 unix_convert(fname,conn,0,&bad_path,&sbuf);
1376 END_PROFILE(SMBopen);
1377 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1380 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1381 &access_mask, &share_mode, &create_disposition, &create_options)) {
1382 END_PROFILE(SMBopen);
1383 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1386 status = open_file_ntcreate(conn,fname,&sbuf,
1395 if (!NT_STATUS_IS_OK(status)) {
1396 END_PROFILE(SMBopen);
1397 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1398 /* We have re-scheduled this call. */
1401 return ERROR_NT(status);
1404 size = sbuf.st_size;
1405 fattr = dos_mode(conn,fname,&sbuf);
1406 mtime = sbuf.st_mtime;
1409 DEBUG(3,("attempt to open a directory %s\n",fname));
1410 close_file(fsp,ERROR_CLOSE);
1411 END_PROFILE(SMBopen);
1412 return ERROR_DOS(ERRDOS,ERRnoaccess);
1415 outsize = set_message(outbuf,7,0,True);
1416 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1417 SSVAL(outbuf,smb_vwv1,fattr);
1418 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1419 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1421 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1423 SIVAL(outbuf,smb_vwv4,(uint32)size);
1424 SSVAL(outbuf,smb_vwv6,deny_mode);
1426 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1427 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1430 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1431 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1433 END_PROFILE(SMBopen);
1437 /****************************************************************************
1438 Reply to an open and X.
1439 ****************************************************************************/
1441 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1444 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1445 int deny_mode = SVAL(inbuf,smb_vwv3);
1446 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1447 /* Breakout the oplock request bits so we can set the
1448 reply bits separately. */
1449 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1450 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1451 int oplock_request = ex_oplock_request | core_oplock_request;
1453 int smb_sattr = SVAL(inbuf,smb_vwv4);
1454 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1456 int smb_ofun = SVAL(inbuf,smb_vwv8);
1460 SMB_STRUCT_STAT sbuf;
1462 BOOL bad_path = False;
1465 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1466 ssize_t retval = -1;
1469 uint32 create_disposition;
1470 uint32 create_options = 0;
1472 START_PROFILE(SMBopenX);
1474 /* If it's an IPC, pass off the pipe handler. */
1476 if (lp_nt_pipe_support()) {
1477 END_PROFILE(SMBopenX);
1478 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1480 END_PROFILE(SMBopenX);
1481 return ERROR_DOS(ERRSRV,ERRaccess);
1485 /* XXXX we need to handle passed times, sattr and flags */
1486 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 END_PROFILE(SMBopenX);
1489 return ERROR_NT(status);
1492 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1494 unix_convert(fname,conn,0,&bad_path,&sbuf);
1496 END_PROFILE(SMBopenX);
1497 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1500 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1503 &create_disposition,
1505 END_PROFILE(SMBopenX);
1506 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1509 status = open_file_ntcreate(conn,fname,&sbuf,
1518 if (!NT_STATUS_IS_OK(status)) {
1519 END_PROFILE(SMBopenX);
1520 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1521 /* We have re-scheduled this call. */
1524 return ERROR_NT(status);
1527 size = sbuf.st_size;
1529 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1530 if the file is truncated or created. */
1531 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1532 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1533 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1534 close_file(fsp,ERROR_CLOSE);
1535 END_PROFILE(SMBopenX);
1536 return ERROR_NT(NT_STATUS_DISK_FULL);
1538 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1540 close_file(fsp,ERROR_CLOSE);
1541 END_PROFILE(SMBopenX);
1542 return ERROR_NT(NT_STATUS_DISK_FULL);
1544 size = get_allocation_size(conn,fsp,&sbuf);
1547 fattr = dos_mode(conn,fname,&sbuf);
1548 mtime = sbuf.st_mtime;
1550 close_file(fsp,ERROR_CLOSE);
1551 END_PROFILE(SMBopenX);
1552 return ERROR_DOS(ERRDOS,ERRnoaccess);
1555 /* If the caller set the extended oplock request bit
1556 and we granted one (by whatever means) - set the
1557 correct bit for extended oplock reply.
1560 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1561 smb_action |= EXTENDED_OPLOCK_GRANTED;
1564 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1565 smb_action |= EXTENDED_OPLOCK_GRANTED;
1568 /* If the caller set the core oplock request bit
1569 and we granted one (by whatever means) - set the
1570 correct bit for core oplock reply.
1573 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1574 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1577 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1578 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1581 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1582 set_message(outbuf,19,0,True);
1584 set_message(outbuf,15,0,True);
1586 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1587 SSVAL(outbuf,smb_vwv3,fattr);
1588 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1589 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1591 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1593 SIVAL(outbuf,smb_vwv6,(uint32)size);
1594 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1595 SSVAL(outbuf,smb_vwv11,smb_action);
1597 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1598 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1601 END_PROFILE(SMBopenX);
1602 return chain_reply(inbuf,outbuf,length,bufsize);
1605 /****************************************************************************
1606 Reply to a SMBulogoffX.
1607 conn POINTER CAN BE NULL HERE !
1608 ****************************************************************************/
1610 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1612 uint16 vuid = SVAL(inbuf,smb_uid);
1613 user_struct *vuser = get_valid_user_struct(vuid);
1614 START_PROFILE(SMBulogoffX);
1617 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1619 /* in user level security we are supposed to close any files
1620 open by this user */
1621 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1622 file_close_user(vuid);
1624 invalidate_vuid(vuid);
1626 set_message(outbuf,2,0,True);
1628 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1630 END_PROFILE(SMBulogoffX);
1631 return chain_reply(inbuf,outbuf,length,bufsize);
1634 /****************************************************************************
1635 Reply to a mknew or a create.
1636 ****************************************************************************/
1638 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1643 uint32 fattr = SVAL(inbuf,smb_vwv0);
1644 BOOL bad_path = False;
1646 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1647 SMB_STRUCT_STAT sbuf;
1649 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1650 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1651 uint32 create_disposition;
1652 uint32 create_options = 0;
1654 START_PROFILE(SMBcreate);
1656 com = SVAL(inbuf,smb_com);
1658 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 END_PROFILE(SMBcreate);
1661 return ERROR_NT(status);
1664 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1666 unix_convert(fname,conn,0,&bad_path,&sbuf);
1668 END_PROFILE(SMBcreate);
1669 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1672 if (fattr & aVOLID) {
1673 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1676 if(com == SMBmknew) {
1677 /* We should fail if file exists. */
1678 create_disposition = FILE_CREATE;
1680 /* Create if file doesn't exist, truncate if it does. */
1681 create_disposition = FILE_OVERWRITE_IF;
1684 /* Open file using ntcreate. */
1685 status = open_file_ntcreate(conn,fname,&sbuf,
1694 if (!NT_STATUS_IS_OK(status)) {
1695 END_PROFILE(SMBcreate);
1696 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1697 /* We have re-scheduled this call. */
1700 return ERROR_NT(status);
1703 outsize = set_message(outbuf,1,0,True);
1704 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1706 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1707 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1710 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1711 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1714 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1715 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1717 END_PROFILE(SMBcreate);
1721 /****************************************************************************
1722 Reply to a create temporary file.
1723 ****************************************************************************/
1725 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1729 uint32 fattr = SVAL(inbuf,smb_vwv0);
1730 BOOL bad_path = False;
1732 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1734 SMB_STRUCT_STAT sbuf;
1737 unsigned int namelen;
1739 START_PROFILE(SMBctemp);
1741 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 END_PROFILE(SMBctemp);
1744 return ERROR_NT(status);
1747 pstrcat(fname,"/TMXXXXXX");
1749 pstrcat(fname,"TMXXXXXX");
1752 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1754 unix_convert(fname,conn,0,&bad_path,&sbuf);
1756 END_PROFILE(SMBctemp);
1757 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1760 tmpfd = smb_mkstemp(fname);
1762 END_PROFILE(SMBctemp);
1763 return(UNIXERROR(ERRDOS,ERRnoaccess));
1766 SMB_VFS_STAT(conn,fname,&sbuf);
1768 /* We should fail if file does not exist. */
1769 status = open_file_ntcreate(conn,fname,&sbuf,
1770 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1771 FILE_SHARE_READ|FILE_SHARE_WRITE,
1778 /* close fd from smb_mkstemp() */
1781 if (!NT_STATUS_IS_OK(status)) {
1782 END_PROFILE(SMBctemp);
1783 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1784 /* We have re-scheduled this call. */
1787 return ERROR_NT(status);
1790 outsize = set_message(outbuf,1,0,True);
1791 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1793 /* the returned filename is relative to the directory */
1794 s = strrchr_m(fname, '/');
1801 p = smb_buf(outbuf);
1803 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1804 thing in the byte section. JRA */
1805 SSVALS(p, 0, -1); /* what is this? not in spec */
1807 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1809 outsize = set_message_end(outbuf, p);
1811 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1812 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1815 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1816 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1819 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1820 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1821 (unsigned int)sbuf.st_mode ) );
1823 END_PROFILE(SMBctemp);
1827 /*******************************************************************
1828 Check if a user is allowed to rename a file.
1829 ********************************************************************/
1831 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1837 if (!CAN_WRITE(conn)) {
1838 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1841 fmode = dos_mode(conn,fname,pst);
1842 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1843 return NT_STATUS_NO_SUCH_FILE;
1846 if (S_ISDIR(pst->st_mode)) {
1847 return NT_STATUS_OK;
1850 status = open_file_ntcreate(conn, fname, pst,
1852 FILE_SHARE_READ|FILE_SHARE_WRITE,
1855 FILE_ATTRIBUTE_NORMAL,
1859 if (!NT_STATUS_IS_OK(status)) {
1860 return NT_STATUS_ACCESS_DENIED;
1862 close_file(fsp,NORMAL_CLOSE);
1863 return NT_STATUS_OK;
1866 /*******************************************************************
1867 Check if a user is allowed to delete a file.
1868 ********************************************************************/
1870 NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
1872 SMB_STRUCT_STAT sbuf;
1877 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1879 if (!CAN_WRITE(conn)) {
1880 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1883 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1884 if(errno == ENOENT) {
1886 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1888 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1891 return map_nt_error_from_unix(errno);
1894 fattr = dos_mode(conn,fname,&sbuf);
1896 /* Can't delete a directory. */
1898 return NT_STATUS_FILE_IS_A_DIRECTORY;
1902 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1903 return NT_STATUS_OBJECT_NAME_INVALID;
1904 #endif /* JRATEST */
1906 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1908 On a Windows share, a file with read-only dosmode can be opened with
1909 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1910 fails with NT_STATUS_CANNOT_DELETE error.
1912 This semantic causes a problem that a user can not
1913 rename a file with read-only dosmode on a Samba share
1914 from a Windows command prompt (i.e. cmd.exe, but can rename
1915 from Windows Explorer).
1918 if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
1919 if (fattr & aRONLY) {
1920 return NT_STATUS_CANNOT_DELETE;
1923 if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1924 return NT_STATUS_NO_SUCH_FILE;
1927 if (check_is_at_open) {
1928 if (!can_delete_file_in_directory(conn, fname)) {
1929 return NT_STATUS_ACCESS_DENIED;
1932 /* On open checks the open itself will check the share mode, so
1933 don't do it here as we'll get it wrong. */
1935 status = open_file_ntcreate(conn, fname, &sbuf,
1940 FILE_ATTRIBUTE_NORMAL,
1944 if (!NT_STATUS_IS_OK(status)) {
1947 close_file(fsp,NORMAL_CLOSE);
1949 return NT_STATUS_OK;
1952 /****************************************************************************
1953 The guts of the unlink command, split out so it may be called by the NT SMB
1955 ****************************************************************************/
1957 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
1963 NTSTATUS error = NT_STATUS_OK;
1964 BOOL bad_path = False;
1966 SMB_STRUCT_STAT sbuf;
1968 *directory = *mask = 0;
1970 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1972 p = strrchr_m(name,'/');
1974 pstrcpy(directory,".");
1978 pstrcpy(directory,name);
1983 * We should only check the mangled cache
1984 * here if unix_convert failed. This means
1985 * that the path in 'mask' doesn't exist
1986 * on the file system and so we need to look
1987 * for a possible mangle. This patch from
1988 * Tine Smukavec <valentin.smukavec@hermes.si>.
1991 if (!rc && mangle_is_mangled(mask,conn->params))
1992 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1995 pstrcat(directory,"/");
1996 pstrcat(directory,mask);
1997 error = can_delete(conn,directory,dirtype,bad_path,False);
1998 if (!NT_STATUS_IS_OK(error))
2001 if (SMB_VFS_UNLINK(conn,directory) == 0) {
2005 struct smb_Dir *dir_hnd = NULL;
2008 if (strequal(mask,"????????.???"))
2011 if (check_name(directory,conn))
2012 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2014 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2015 the pattern matches against the long name, otherwise the short name
2016 We don't implement this yet XXXX
2021 error = NT_STATUS_NO_SUCH_FILE;
2023 while ((dname = ReadDirName(dir_hnd, &offset))) {
2026 BOOL sys_direntry = False;
2027 pstrcpy(fname,dname);
2029 if (!is_visible_file(conn, directory, dname, &st, True)) {
2033 /* Quick check for "." and ".." */
2034 if (fname[0] == '.') {
2035 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2036 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
2037 sys_direntry = True;
2044 if(!mask_match(fname, mask, conn->case_sensitive))
2048 error = NT_STATUS_OBJECT_NAME_INVALID;
2049 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
2054 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2055 error = can_delete(conn,fname,dirtype,bad_path,False);
2056 if (!NT_STATUS_IS_OK(error)) {
2059 if (SMB_VFS_UNLINK(conn,fname) == 0)
2061 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2067 if (count == 0 && NT_STATUS_IS_OK(error)) {
2068 error = map_nt_error_from_unix(errno);
2074 /****************************************************************************
2076 ****************************************************************************/
2078 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2085 BOOL path_contains_wcard = False;
2087 START_PROFILE(SMBunlink);
2089 dirtype = SVAL(inbuf,smb_vwv0);
2091 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2092 if (!NT_STATUS_IS_OK(status)) {
2093 END_PROFILE(SMBunlink);
2094 return ERROR_NT(status);
2097 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
2099 DEBUG(3,("reply_unlink : %s\n",name));
2101 status = unlink_internals(conn, dirtype, name, path_contains_wcard);
2102 if (!NT_STATUS_IS_OK(status)) {
2103 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2104 /* We have re-scheduled this call. */
2107 return ERROR_NT(status);
2111 * Win2k needs a changenotify request response before it will
2112 * update after a rename..
2114 process_pending_change_notify_queue((time_t)0);
2116 outsize = set_message(outbuf,0,0,False);
2118 END_PROFILE(SMBunlink);
2122 /****************************************************************************
2124 ****************************************************************************/
2126 static void fail_readraw(void)
2129 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2131 exit_server(errstr);
2134 #if defined(WITH_SENDFILE)
2135 /****************************************************************************
2136 Fake (read/write) sendfile. Returns -1 on read or write fail.
2137 ****************************************************************************/
2139 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2143 /* Paranioa check... */
2144 if (nread > bufsize) {
2149 ret = read_file(fsp,buf,startpos,nread);
2155 /* If we had a short read, fill with zeros. */
2157 memset(buf, '\0', nread - ret);
2160 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2164 return (ssize_t)nread;
2168 /****************************************************************************
2169 Use sendfile in readbraw.
2170 ****************************************************************************/
2172 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2173 ssize_t mincount, char *outbuf, int out_buffsize)
2177 #if defined(WITH_SENDFILE)
2179 * We can only use sendfile on a non-chained packet
2180 * but we can use on a non-oplocked file. tridge proved this
2181 * on a train in Germany :-). JRA.
2182 * reply_readbraw has already checked the length.
2185 if ( (chain_size == 0) && (nread > 0) &&
2186 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2189 _smb_setlen(outbuf,nread);
2190 header.data = (uint8 *)outbuf;
2194 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2195 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2196 if (errno == ENOSYS) {
2197 goto normal_readbraw;
2201 * Special hack for broken Linux with no working sendfile. If we
2202 * return EINTR we sent the header but not the rest of the data.
2203 * Fake this up by doing read/write calls.
2205 if (errno == EINTR) {
2206 /* Ensure we don't do this again. */
2207 set_use_sendfile(SNUM(conn), False);
2208 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2210 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2211 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2212 fsp->fsp_name, strerror(errno) ));
2213 exit_server("send_file_readbraw fake_sendfile failed");
2218 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2219 fsp->fsp_name, strerror(errno) ));
2220 exit_server("send_file_readbraw sendfile failed");
2230 ret = read_file(fsp,outbuf+4,startpos,nread);
2231 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2240 _smb_setlen(outbuf,ret);
2241 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2245 /****************************************************************************
2246 Reply to a readbraw (core+ protocol).
2247 ****************************************************************************/
2249 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2251 ssize_t maxcount,mincount;
2254 char *header = outbuf;
2256 START_PROFILE(SMBreadbraw);
2258 if (srv_is_signing_active()) {
2259 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2263 * Special check if an oplock break has been issued
2264 * and the readraw request croses on the wire, we must
2265 * return a zero length response here.
2268 fsp = file_fsp(inbuf,smb_vwv0);
2270 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2272 * fsp could be NULL here so use the value from the packet. JRA.
2274 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2275 _smb_setlen(header,0);
2276 if (write_data(smbd_server_fd(),header,4) != 4)
2278 END_PROFILE(SMBreadbraw);
2282 CHECK_FSP(fsp,conn);
2284 flush_write_cache(fsp, READRAW_FLUSH);
2286 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2287 if(CVAL(inbuf,smb_wct) == 10) {
2289 * This is a large offset (64 bit) read.
2291 #ifdef LARGE_SMB_OFF_T
2293 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2295 #else /* !LARGE_SMB_OFF_T */
2298 * Ensure we haven't been sent a >32 bit offset.
2301 if(IVAL(inbuf,smb_vwv8) != 0) {
2302 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2303 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2304 _smb_setlen(header,0);
2305 if (write_data(smbd_server_fd(),header,4) != 4)
2307 END_PROFILE(SMBreadbraw);
2311 #endif /* LARGE_SMB_OFF_T */
2314 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2315 _smb_setlen(header,0);
2316 if (write_data(smbd_server_fd(),header,4) != 4)
2318 END_PROFILE(SMBreadbraw);
2322 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2323 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2325 /* ensure we don't overrun the packet size */
2326 maxcount = MIN(65535,maxcount);
2328 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2332 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2336 if (startpos >= size) {
2339 nread = MIN(maxcount,(size - startpos));
2343 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2344 if (nread < mincount)
2348 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2349 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2351 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2353 DEBUG(5,("readbraw finished\n"));
2354 END_PROFILE(SMBreadbraw);
2359 #define DBGC_CLASS DBGC_LOCKING
2361 /****************************************************************************
2362 Reply to a lockread (core+ protocol).
2363 ****************************************************************************/
2365 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2373 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2374 BOOL my_lock_ctx = False;
2375 START_PROFILE(SMBlockread);
2377 CHECK_FSP(fsp,conn);
2378 if (!CHECK_READ(fsp,inbuf)) {
2379 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2382 release_level_2_oplocks_on_change(fsp);
2384 numtoread = SVAL(inbuf,smb_vwv1);
2385 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2387 outsize = set_message(outbuf,5,3,True);
2388 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2389 data = smb_buf(outbuf) + 3;
2392 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2393 * protocol request that predates the read/write lock concept.
2394 * Thus instead of asking for a read lock here we need to ask
2395 * for a write lock. JRA.
2396 * Note that the requested lock size is unaffected by max_recv.
2399 status = do_lock_spin(fsp,
2400 (uint32)SVAL(inbuf,smb_pid),
2401 (SMB_BIG_UINT)numtoread,
2402 (SMB_BIG_UINT)startpos,
2407 if (NT_STATUS_V(status)) {
2410 * We used to make lockread a blocking lock. It turns out
2411 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2415 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2417 * A blocking lock was requested. Package up
2418 * this smb into a queued request and push it
2419 * onto the blocking lock queue.
2421 if(push_blocking_lock_request(inbuf, length,
2425 SVAL(inbuf,smb_pid),
2428 (SMB_BIG_UINT)startpos,
2429 (SMB_BIG_UINT)numtoread)) {
2430 END_PROFILE(SMBlockread);
2435 END_PROFILE(SMBlockread);
2436 return ERROR_NT(status);
2440 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2443 if (numtoread > max_recv) {
2444 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2445 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2446 (unsigned int)numtoread, (unsigned int)max_recv ));
2447 numtoread = MIN(numtoread,max_recv);
2449 nread = read_file(fsp,data,startpos,numtoread);
2452 END_PROFILE(SMBlockread);
2453 return(UNIXERROR(ERRDOS,ERRnoaccess));
2457 SSVAL(outbuf,smb_vwv0,nread);
2458 SSVAL(outbuf,smb_vwv5,nread+3);
2459 SSVAL(smb_buf(outbuf),1,nread);
2461 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2462 fsp->fnum, (int)numtoread, (int)nread));
2464 END_PROFILE(SMBlockread);
2469 #define DBGC_CLASS DBGC_ALL
2471 /****************************************************************************
2473 ****************************************************************************/
2475 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2482 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2483 START_PROFILE(SMBread);
2485 CHECK_FSP(fsp,conn);
2486 if (!CHECK_READ(fsp,inbuf)) {
2487 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2490 numtoread = SVAL(inbuf,smb_vwv1);
2491 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2493 outsize = set_message(outbuf,5,3,True);
2494 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2496 * The requested read size cannot be greater than max_recv. JRA.
2498 if (numtoread > max_recv) {
2499 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2500 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2501 (unsigned int)numtoread, (unsigned int)max_recv ));
2502 numtoread = MIN(numtoread,max_recv);
2505 data = smb_buf(outbuf) + 3;
2507 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2508 END_PROFILE(SMBread);
2509 return ERROR_DOS(ERRDOS,ERRlock);
2513 nread = read_file(fsp,data,startpos,numtoread);
2516 END_PROFILE(SMBread);
2517 return(UNIXERROR(ERRDOS,ERRnoaccess));
2521 SSVAL(outbuf,smb_vwv0,nread);
2522 SSVAL(outbuf,smb_vwv5,nread+3);
2523 SCVAL(smb_buf(outbuf),0,1);
2524 SSVAL(smb_buf(outbuf),1,nread);
2526 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2527 fsp->fnum, (int)numtoread, (int)nread ) );
2529 END_PROFILE(SMBread);
2533 /****************************************************************************
2534 Reply to a read and X - possibly using sendfile.
2535 ****************************************************************************/
2537 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2538 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2542 char *data = smb_buf(outbuf);
2544 #if defined(WITH_SENDFILE)
2546 * We can only use sendfile on a non-chained packet
2547 * but we can use on a non-oplocked file. tridge proved this
2548 * on a train in Germany :-). JRA.
2551 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2552 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2553 SMB_STRUCT_STAT sbuf;
2556 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2557 return(UNIXERROR(ERRDOS,ERRnoaccess));
2559 if (startpos > sbuf.st_size)
2562 if (smb_maxcnt > (sbuf.st_size - startpos))
2563 smb_maxcnt = (sbuf.st_size - startpos);
2565 if (smb_maxcnt == 0)
2569 * Set up the packet header before send. We
2570 * assume here the sendfile will work (get the
2571 * correct amount of data).
2574 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2575 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2576 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2577 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2578 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2579 SCVAL(outbuf,smb_vwv0,0xFF);
2580 set_message(outbuf,12,smb_maxcnt,False);
2581 header.data = (uint8 *)outbuf;
2582 header.length = data - outbuf;
2585 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2586 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2587 if (errno == ENOSYS) {
2592 * Special hack for broken Linux with no working sendfile. If we
2593 * return EINTR we sent the header but not the rest of the data.
2594 * Fake this up by doing read/write calls.
2597 if (errno == EINTR) {
2598 /* Ensure we don't do this again. */
2599 set_use_sendfile(SNUM(conn), False);
2600 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2602 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2603 len_outbuf - (data-outbuf))) == -1) {
2604 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2605 fsp->fsp_name, strerror(errno) ));
2606 exit_server("send_file_readX: fake_sendfile failed");
2608 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2609 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2610 /* Returning -1 here means successful sendfile. */
2614 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2615 fsp->fsp_name, strerror(errno) ));
2616 exit_server("send_file_readX sendfile failed");
2619 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2620 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2621 /* Returning -1 here means successful sendfile. */
2629 nread = read_file(fsp,data,startpos,smb_maxcnt);
2632 return(UNIXERROR(ERRDOS,ERRnoaccess));
2635 outsize = set_message(outbuf,12,nread,False);
2636 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2637 SSVAL(outbuf,smb_vwv5,nread);
2638 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2639 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2640 SSVAL(smb_buf(outbuf),-2,nread);
2642 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2643 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2645 /* Returning the number of bytes we want to send back - including header. */
2649 /****************************************************************************
2650 Reply to a read and X.
2651 ****************************************************************************/
2653 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2655 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2656 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2658 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2660 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2663 START_PROFILE(SMBreadX);
2665 /* If it's an IPC, pass off the pipe handler. */
2667 END_PROFILE(SMBreadX);
2668 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2671 CHECK_FSP(fsp,conn);
2672 if (!CHECK_READ(fsp,inbuf)) {
2673 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2676 set_message(outbuf,12,0,True);
2678 if (global_client_caps & CAP_LARGE_READX) {
2679 if (SVAL(inbuf,smb_vwv7) == 1) {
2680 smb_maxcnt |= (1<<16);
2682 if (smb_maxcnt > BUFFER_SIZE) {
2683 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2684 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2685 END_PROFILE(SMBreadX);
2686 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2690 if(CVAL(inbuf,smb_wct) == 12) {
2691 #ifdef LARGE_SMB_OFF_T
2693 * This is a large offset (64 bit) read.
2695 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2697 #else /* !LARGE_SMB_OFF_T */
2700 * Ensure we haven't been sent a >32 bit offset.
2703 if(IVAL(inbuf,smb_vwv10) != 0) {
2704 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2705 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2706 END_PROFILE(SMBreadX);
2707 return ERROR_DOS(ERRDOS,ERRbadaccess);
2710 #endif /* LARGE_SMB_OFF_T */
2714 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2715 END_PROFILE(SMBreadX);
2716 return ERROR_DOS(ERRDOS,ERRlock);
2719 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2720 END_PROFILE(SMBreadX);
2724 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2726 nread = chain_reply(inbuf,outbuf,length,bufsize);
2728 END_PROFILE(SMBreadX);
2732 /****************************************************************************
2733 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2734 ****************************************************************************/
2736 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2739 ssize_t total_written=0;
2740 size_t numtowrite=0;
2745 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2747 START_PROFILE(SMBwritebraw);
2749 if (srv_is_signing_active()) {
2750 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2753 CHECK_FSP(fsp,conn);
2754 if (!CHECK_WRITE(fsp)) {
2755 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2758 tcount = IVAL(inbuf,smb_vwv1);
2759 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2760 write_through = BITSETW(inbuf+smb_vwv7,0);
2762 /* We have to deal with slightly different formats depending
2763 on whether we are using the core+ or lanman1.0 protocol */
2765 if(Protocol <= PROTOCOL_COREPLUS) {
2766 numtowrite = SVAL(smb_buf(inbuf),-2);
2767 data = smb_buf(inbuf);
2769 numtowrite = SVAL(inbuf,smb_vwv10);
2770 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2773 /* force the error type */
2774 SCVAL(inbuf,smb_com,SMBwritec);
2775 SCVAL(outbuf,smb_com,SMBwritec);
2777 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2778 END_PROFILE(SMBwritebraw);
2779 return(ERROR_DOS(ERRDOS,ERRlock));
2783 nwritten = write_file(fsp,data,startpos,numtowrite);
2785 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2786 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2788 if (nwritten < (ssize_t)numtowrite) {
2789 END_PROFILE(SMBwritebraw);
2790 return(UNIXERROR(ERRHRD,ERRdiskfull));
2793 total_written = nwritten;
2795 /* Return a message to the redirector to tell it to send more bytes */
2796 SCVAL(outbuf,smb_com,SMBwritebraw);
2797 SSVALS(outbuf,smb_vwv0,-1);
2798 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2800 if (!send_smb(smbd_server_fd(),outbuf))
2801 exit_server("reply_writebraw: send_smb failed.");
2803 /* Now read the raw data into the buffer and write it */
2804 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2805 exit_server("secondary writebraw failed");
2808 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2809 numtowrite = smb_len(inbuf);
2811 /* Set up outbuf to return the correct return */
2812 outsize = set_message(outbuf,1,0,True);
2813 SCVAL(outbuf,smb_com,SMBwritec);
2815 if (numtowrite != 0) {
2817 if (numtowrite > BUFFER_SIZE) {
2818 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2819 (unsigned int)numtowrite ));
2820 exit_server("secondary writebraw failed");
2823 if (tcount > nwritten+numtowrite) {
2824 DEBUG(3,("Client overestimated the write %d %d %d\n",
2825 (int)tcount,(int)nwritten,(int)numtowrite));
2828 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2829 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2831 exit_server("secondary writebraw failed");
2834 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2836 if (nwritten < (ssize_t)numtowrite) {
2837 SCVAL(outbuf,smb_rcls,ERRHRD);
2838 SSVAL(outbuf,smb_err,ERRdiskfull);
2842 total_written += nwritten;
2845 SSVAL(outbuf,smb_vwv0,total_written);
2847 sync_file(conn, fsp, write_through);
2849 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2850 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2852 /* we won't return a status if write through is not selected - this follows what WfWg does */
2853 END_PROFILE(SMBwritebraw);
2854 if (!write_through && total_written==tcount) {
2856 #if RABBIT_PELLET_FIX
2858 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2859 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2861 if (!send_keepalive(smbd_server_fd()))
2862 exit_server("reply_writebraw: send of keepalive failed");
2871 #define DBGC_CLASS DBGC_LOCKING
2873 /****************************************************************************
2874 Reply to a writeunlock (core+).
2875 ****************************************************************************/
2877 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2878 int size, int dum_buffsize)
2880 ssize_t nwritten = -1;
2884 NTSTATUS status = NT_STATUS_OK;
2885 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2887 START_PROFILE(SMBwriteunlock);
2889 CHECK_FSP(fsp,conn);
2890 if (!CHECK_WRITE(fsp)) {
2891 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2894 numtowrite = SVAL(inbuf,smb_vwv1);
2895 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2896 data = smb_buf(inbuf) + 3;
2898 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2899 END_PROFILE(SMBwriteunlock);
2900 return ERROR_DOS(ERRDOS,ERRlock);
2903 /* The special X/Open SMB protocol handling of
2904 zero length writes is *NOT* done for
2906 if(numtowrite == 0) {
2909 nwritten = write_file(fsp,data,startpos,numtowrite);
2912 sync_file(conn, fsp, False /* write through */);
2914 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2915 END_PROFILE(SMBwriteunlock);
2916 return(UNIXERROR(ERRHRD,ERRdiskfull));
2920 status = do_unlock(fsp,
2921 (uint32)SVAL(inbuf,smb_pid),
2922 (SMB_BIG_UINT)numtowrite,
2923 (SMB_BIG_UINT)startpos,
2926 if (NT_STATUS_V(status)) {
2927 END_PROFILE(SMBwriteunlock);
2928 return ERROR_NT(status);
2932 outsize = set_message(outbuf,1,0,True);
2934 SSVAL(outbuf,smb_vwv0,nwritten);
2936 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2937 fsp->fnum, (int)numtowrite, (int)nwritten));
2939 END_PROFILE(SMBwriteunlock);
2944 #define DBGC_CLASS DBGC_ALL
2946 /****************************************************************************
2948 ****************************************************************************/
2950 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2953 ssize_t nwritten = -1;
2956 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2958 START_PROFILE(SMBwrite);
2960 /* If it's an IPC, pass off the pipe handler. */
2962 END_PROFILE(SMBwrite);
2963 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2966 CHECK_FSP(fsp,conn);
2967 if (!CHECK_WRITE(fsp)) {
2968 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2971 numtowrite = SVAL(inbuf,smb_vwv1);
2972 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2973 data = smb_buf(inbuf) + 3;
2975 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2976 END_PROFILE(SMBwrite);
2977 return ERROR_DOS(ERRDOS,ERRlock);
2981 * X/Open SMB protocol says that if smb_vwv1 is
2982 * zero then the file size should be extended or
2983 * truncated to the size given in smb_vwv[2-3].
2986 if(numtowrite == 0) {
2988 * This is actually an allocate call, and set EOF. JRA.
2990 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2992 END_PROFILE(SMBwrite);
2993 return ERROR_NT(NT_STATUS_DISK_FULL);
2995 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2997 END_PROFILE(SMBwrite);
2998 return ERROR_NT(NT_STATUS_DISK_FULL);
3001 nwritten = write_file(fsp,data,startpos,numtowrite);
3003 sync_file(conn, fsp, False);
3005 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3006 END_PROFILE(SMBwrite);
3007 return(UNIXERROR(ERRHRD,ERRdiskfull));
3010 outsize = set_message(outbuf,1,0,True);
3012 SSVAL(outbuf,smb_vwv0,nwritten);
3014 if (nwritten < (ssize_t)numtowrite) {
3015 SCVAL(outbuf,smb_rcls,ERRHRD);
3016 SSVAL(outbuf,smb_err,ERRdiskfull);
3019 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3021 END_PROFILE(SMBwrite);
3025 /****************************************************************************
3026 Reply to a write and X.
3027 ****************************************************************************/
3029 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3031 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3032 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3033 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3034 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3035 ssize_t nwritten = -1;
3036 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3037 unsigned int smblen = smb_len(inbuf);
3039 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3040 START_PROFILE(SMBwriteX);
3042 /* If it's an IPC, pass off the pipe handler. */
3044 END_PROFILE(SMBwriteX);
3045 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3048 CHECK_FSP(fsp,conn);
3049 if (!CHECK_WRITE(fsp)) {
3050 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3053 set_message(outbuf,6,0,True);
3055 /* Deal with possible LARGE_WRITEX */
3057 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3060 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3061 END_PROFILE(SMBwriteX);
3062 return ERROR_DOS(ERRDOS,ERRbadmem);
3065 data = smb_base(inbuf) + smb_doff;
3067 if(CVAL(inbuf,smb_wct) == 14) {
3068 #ifdef LARGE_SMB_OFF_T
3070 * This is a large offset (64 bit) write.
3072 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3074 #else /* !LARGE_SMB_OFF_T */
3077 * Ensure we haven't been sent a >32 bit offset.
3080 if(IVAL(inbuf,smb_vwv12) != 0) {
3081 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3082 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3083 END_PROFILE(SMBwriteX);
3084 return ERROR_DOS(ERRDOS,ERRbadaccess);
3087 #endif /* LARGE_SMB_OFF_T */
3090 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3091 END_PROFILE(SMBwriteX);
3092 return ERROR_DOS(ERRDOS,ERRlock);
3095 /* X/Open SMB protocol says that, unlike SMBwrite
3096 if the length is zero then NO truncation is
3097 done, just a write of zero. To truncate a file,
3100 if(numtowrite == 0) {
3104 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3105 fsp,data,startpos,numtowrite)) {
3106 END_PROFILE(SMBwriteX);
3110 nwritten = write_file(fsp,data,startpos,numtowrite);
3113 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3114 END_PROFILE(SMBwriteX);
3115 return(UNIXERROR(ERRHRD,ERRdiskfull));
3118 SSVAL(outbuf,smb_vwv2,nwritten);
3120 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3122 if (nwritten < (ssize_t)numtowrite) {
3123 SCVAL(outbuf,smb_rcls,ERRHRD);
3124 SSVAL(outbuf,smb_err,ERRdiskfull);
3127 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3128 fsp->fnum, (int)numtowrite, (int)nwritten));
3130 sync_file(conn, fsp, write_through);
3132 END_PROFILE(SMBwriteX);
3133 return chain_reply(inbuf,outbuf,length,bufsize);
3136 /****************************************************************************
3138 ****************************************************************************/
3140 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3146 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3147 START_PROFILE(SMBlseek);
3149 CHECK_FSP(fsp,conn);
3151 flush_write_cache(fsp, SEEK_FLUSH);
3153 mode = SVAL(inbuf,smb_vwv1) & 3;
3154 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3155 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3164 res = fsp->fh->pos + startpos;
3175 if (umode == SEEK_END) {
3176 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3177 if(errno == EINVAL) {
3178 SMB_OFF_T current_pos = startpos;
3179 SMB_STRUCT_STAT sbuf;
3181 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3182 END_PROFILE(SMBlseek);
3183 return(UNIXERROR(ERRDOS,ERRnoaccess));
3186 current_pos += sbuf.st_size;
3188 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3193 END_PROFILE(SMBlseek);
3194 return(UNIXERROR(ERRDOS,ERRnoaccess));
3200 outsize = set_message(outbuf,2,0,True);
3201 SIVAL(outbuf,smb_vwv0,res);
3203 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3204 fsp->fnum, (double)startpos, (double)res, mode));
3206 END_PROFILE(SMBlseek);
3210 /****************************************************************************
3212 ****************************************************************************/
3214 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3216 int outsize = set_message(outbuf,0,0,False);
3217 uint16 fnum = SVAL(inbuf,smb_vwv0);
3218 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3219 START_PROFILE(SMBflush);
3222 CHECK_FSP(fsp,conn);
3225 file_sync_all(conn);
3227 sync_file(conn,fsp, True);
3230 DEBUG(3,("flush\n"));
3231 END_PROFILE(SMBflush);
3235 /****************************************************************************
3237 conn POINTER CAN BE NULL HERE !
3238 ****************************************************************************/
3240 int reply_exit(connection_struct *conn,
3241 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3244 START_PROFILE(SMBexit);
3246 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3248 outsize = set_message(outbuf,0,0,False);
3250 DEBUG(3,("exit\n"));
3252 END_PROFILE(SMBexit);
3256 /****************************************************************************
3257 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3258 ****************************************************************************/
3260 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3265 int32 eclass = 0, err = 0;
3266 files_struct *fsp = NULL;
3267 START_PROFILE(SMBclose);
3269 outsize = set_message(outbuf,0,0,False);
3271 /* If it's an IPC, pass off to the pipe handler. */
3273 END_PROFILE(SMBclose);
3274 return reply_pipe_close(conn, inbuf,outbuf);
3277 fsp = file_fsp(inbuf,smb_vwv0);
3280 * We can only use CHECK_FSP if we know it's not a directory.
3283 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3284 END_PROFILE(SMBclose);
3285 return ERROR_DOS(ERRDOS,ERRbadfid);
3288 if(fsp->is_directory) {
3290 * Special case - close NT SMB directory handle.
3292 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3293 close_file(fsp,NORMAL_CLOSE);
3296 * Close ordinary file.
3301 /* Save the name for time set in close. */
3302 pstrcpy( file_name, fsp->fsp_name);
3304 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3305 fsp->fh->fd, fsp->fnum,
3306 conn->num_files_open));
3309 * Take care of any time sent in the close.
3312 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3313 fsp_set_pending_modtime(fsp, mtime);
3316 * close_file() returns the unix errno if an error
3317 * was detected on close - normally this is due to
3318 * a disk full error. If not then it was probably an I/O error.
3321 if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
3323 END_PROFILE(SMBclose);
3324 return (UNIXERROR(ERRHRD,ERRgeneral));
3328 /* We have a cached error */
3330 END_PROFILE(SMBclose);
3331 return ERROR_DOS(eclass,err);
3334 END_PROFILE(SMBclose);
3338 /****************************************************************************
3339 Reply to a writeclose (Core+ protocol).
3340 ****************************************************************************/
3342 int reply_writeclose(connection_struct *conn,
3343 char *inbuf,char *outbuf, int size, int dum_buffsize)
3346 ssize_t nwritten = -1;
3352 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3353 START_PROFILE(SMBwriteclose);
3355 CHECK_FSP(fsp,conn);
3356 if (!CHECK_WRITE(fsp)) {
3357 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3360 numtowrite = SVAL(inbuf,smb_vwv1);
3361 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3362 mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3363 data = smb_buf(inbuf) + 1;
3365 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3366 END_PROFILE(SMBwriteclose);
3367 return ERROR_DOS(ERRDOS,ERRlock);
3370 nwritten = write_file(fsp,data,startpos,numtowrite);
3372 set_filetime(conn, fsp->fsp_name,mtime);
3375 * More insanity. W2K only closes the file if writelen > 0.
3380 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3382 close_err = close_file(fsp,NORMAL_CLOSE);
3385 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3386 fsp->fnum, (int)numtowrite, (int)nwritten,
3387 conn->num_files_open));
3389 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3390 END_PROFILE(SMBwriteclose);
3391 return(UNIXERROR(ERRHRD,ERRdiskfull));
3394 if(close_err != 0) {
3396 END_PROFILE(SMBwriteclose);
3397 return(UNIXERROR(ERRHRD,ERRgeneral));
3400 outsize = set_message(outbuf,1,0,True);
3402 SSVAL(outbuf,smb_vwv0,nwritten);
3403 END_PROFILE(SMBwriteclose);
3408 #define DBGC_CLASS DBGC_LOCKING
3410 /****************************************************************************
3412 ****************************************************************************/
3414 int reply_lock(connection_struct *conn,
3415 char *inbuf,char *outbuf, int length, int dum_buffsize)
3417 int outsize = set_message(outbuf,0,0,False);
3418 SMB_BIG_UINT count,offset;
3420 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3421 BOOL my_lock_ctx = False;
3423 START_PROFILE(SMBlock);
3425 CHECK_FSP(fsp,conn);
3427 release_level_2_oplocks_on_change(fsp);
3429 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3430 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3432 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3433 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3435 status = do_lock_spin(fsp,
3436 (uint32)SVAL(inbuf,smb_pid),
3442 if (NT_STATUS_V(status)) {
3444 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3445 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3447 * A blocking lock was requested. Package up
3448 * this smb into a queued request and push it
3449 * onto the blocking lock queue.
3451 if(push_blocking_lock_request(inbuf, length,
3455 SVAL(inbuf,smb_pid),
3459 END_PROFILE(SMBlock);
3464 END_PROFILE(SMBlock);
3465 return ERROR_NT(status);
3468 END_PROFILE(SMBlock);
3472 /****************************************************************************
3474 ****************************************************************************/
3476 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3479 int outsize = set_message(outbuf,0,0,False);
3480 SMB_BIG_UINT count,offset;
3482 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3483 START_PROFILE(SMBunlock);
3485 CHECK_FSP(fsp,conn);
3487 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3488 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3490 status = do_unlock(fsp,
3491 (uint32)SVAL(inbuf,smb_pid),
3496 if (NT_STATUS_V(status)) {
3497 END_PROFILE(SMBunlock);
3498 return ERROR_NT(status);
3501 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3502 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3504 END_PROFILE(SMBunlock);
3509 #define DBGC_CLASS DBGC_ALL
3511 /****************************************************************************
3513 conn POINTER CAN BE NULL HERE !
3514 ****************************************************************************/
3516 int reply_tdis(connection_struct *conn,
3517 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3519 int outsize = set_message(outbuf,0,0,False);
3521 START_PROFILE(SMBtdis);
3523 vuid = SVAL(inbuf,smb_uid);
3526 DEBUG(4,("Invalid connection in tdis\n"));
3527 END_PROFILE(SMBtdis);
3528 return ERROR_DOS(ERRSRV,ERRinvnid);
3533 close_cnum(conn,vuid);
3535 END_PROFILE(SMBtdis);
3539 /****************************************************************************
3541 conn POINTER CAN BE NULL HERE !
3542 ****************************************************************************/
3544 int reply_echo(connection_struct *conn,
3545 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3547 int smb_reverb = SVAL(inbuf,smb_vwv0);
3549 unsigned int data_len = smb_buflen(inbuf);
3550 int outsize = set_message(outbuf,1,data_len,True);
3551 START_PROFILE(SMBecho);
3553 if (data_len > BUFFER_SIZE) {
3554 DEBUG(0,("reply_echo: data_len too large.\n"));
3555 END_PROFILE(SMBecho);
3559 /* copy any incoming data back out */
3561 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3563 if (smb_reverb > 100) {
3564 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3568 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3569 SSVAL(outbuf,smb_vwv0,seq_num);
3571 smb_setlen(outbuf,outsize - 4);
3574 if (!send_smb(smbd_server_fd(),outbuf))
3575 exit_server("reply_echo: send_smb failed.");
3578 DEBUG(3,("echo %d times\n", smb_reverb));
3582 END_PROFILE(SMBecho);
3586 /****************************************************************************
3587 Reply to a printopen.
3588 ****************************************************************************/
3590 int reply_printopen(connection_struct *conn,
3591 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3597 START_PROFILE(SMBsplopen);
3599 if (!CAN_PRINT(conn)) {
3600 END_PROFILE(SMBsplopen);
3601 return ERROR_DOS(ERRDOS,ERRnoaccess);
3604 /* Open for exclusive use, write only. */
3605 status = print_fsp_open(conn, NULL, &fsp);
3607 if (!NT_STATUS_IS_OK(status)) {
3608 END_PROFILE(SMBsplopen);
3609 return(ERROR_NT(status));
3612 outsize = set_message(outbuf,1,0,True);
3613 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3615 DEBUG(3,("openprint fd=%d fnum=%d\n",
3616 fsp->fh->fd, fsp->fnum));
3618 END_PROFILE(SMBsplopen);
3622 /****************************************************************************
3623 Reply to a printclose.
3624 ****************************************************************************/
3626 int reply_printclose(connection_struct *conn,
3627 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3629 int outsize = set_message(outbuf,0,0,False);
3630 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3632 START_PROFILE(SMBsplclose);
3634 CHECK_FSP(fsp,conn);
3636 if (!CAN_PRINT(conn)) {
3637 END_PROFILE(SMBsplclose);
3638 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3641 DEBUG(3,("printclose fd=%d fnum=%d\n",
3642 fsp->fh->fd,fsp->fnum));
3644 close_err = close_file(fsp,NORMAL_CLOSE);
3646 if(close_err != 0) {
3648 END_PROFILE(SMBsplclose);
3649 return(UNIXERROR(ERRHRD,ERRgeneral));
3652 END_PROFILE(SMBsplclose);
3656 /****************************************************************************
3657 Reply to a printqueue.
3658 ****************************************************************************/
3660 int reply_printqueue(connection_struct *conn,
3661 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3663 int outsize = set_message(outbuf,2,3,True);
3664 int max_count = SVAL(inbuf,smb_vwv0);
3665 int start_index = SVAL(inbuf,smb_vwv1);
3666 START_PROFILE(SMBsplretq);
3668 /* we used to allow the client to get the cnum wrong, but that
3669 is really quite gross and only worked when there was only
3670 one printer - I think we should now only accept it if they
3671 get it right (tridge) */
3672 if (!CAN_PRINT(conn)) {
3673 END_PROFILE(SMBsplretq);
3674 return ERROR_DOS(ERRDOS,ERRnoaccess);
3677 SSVAL(outbuf,smb_vwv0,0);
3678 SSVAL(outbuf,smb_vwv1,0);
3679 SCVAL(smb_buf(outbuf),0,1);
3680 SSVAL(smb_buf(outbuf),1,0);
3682 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3683 start_index, max_count));
3686 print_queue_struct *queue = NULL;
3687 print_status_struct status;
3688 char *p = smb_buf(outbuf) + 3;
3689 int count = print_queue_status(SNUM(conn), &queue, &status);
3690 int num_to_get = ABS(max_count);
3691 int first = (max_count>0?start_index:start_index+max_count+1);
3697 num_to_get = MIN(num_to_get,count-first);
3700 for (i=first;i<first+num_to_get;i++) {
3701 srv_put_dos_date2(p,0,queue[i].time);
3702 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3703 SSVAL(p,5, queue[i].job);
3704 SIVAL(p,7,queue[i].size);
3706 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3711 outsize = set_message(outbuf,2,28*count+3,False);
3712 SSVAL(outbuf,smb_vwv0,count);
3713 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3714 SCVAL(smb_buf(outbuf),0,1);
3715 SSVAL(smb_buf(outbuf),1,28*count);
3720 DEBUG(3,("%d entries returned in queue\n",count));
3723 END_PROFILE(SMBsplretq);
3727 /****************************************************************************
3728 Reply to a printwrite.
3729 ****************************************************************************/
3731 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3734 int outsize = set_message(outbuf,0,0,False);
3736 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3738 START_PROFILE(SMBsplwr);
3740 if (!CAN_PRINT(conn)) {
3741 END_PROFILE(SMBsplwr);
3742 return ERROR_DOS(ERRDOS,ERRnoaccess);
3745 CHECK_FSP(fsp,conn);
3746 if (!CHECK_WRITE(fsp)) {
3747 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3750 numtowrite = SVAL(smb_buf(inbuf),1);
3751 data = smb_buf(inbuf) + 3;
3753 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3754 END_PROFILE(SMBsplwr);
3755 return(UNIXERROR(ERRHRD,ERRdiskfull));
3758 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3760 END_PROFILE(SMBsplwr);
3764 /****************************************************************************
3765 The guts of the mkdir command, split out so it may be called by the NT SMB
3767 ****************************************************************************/
3769 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3773 if(!CAN_WRITE(conn)) {
3774 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3776 return map_nt_error_from_unix(errno);
3780 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3783 if (!check_name(directory, conn)) {
3784 if(errno == ENOENT) {
3786 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3788 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3791 return map_nt_error_from_unix(errno);
3794 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3796 if(errno == ENOENT) {
3797 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3799 return map_nt_error_from_unix(errno);
3802 return NT_STATUS_OK;
3805 /****************************************************************************
3807 ****************************************************************************/
3809 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3814 BOOL bad_path = False;
3815 SMB_STRUCT_STAT sbuf;
3817 START_PROFILE(SMBmkdir);
3819 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3820 if (!NT_STATUS_IS_OK(status)) {
3821 END_PROFILE(SMBmkdir);
3822 return ERROR_NT(status);
3825 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3827 unix_convert(directory,conn,0,&bad_path,&sbuf);
3829 if( is_ntfs_stream_name(directory)) {
3830 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3831 END_PROFILE(SMBmkdir);
3832 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
3835 status = mkdir_internal(conn, directory,bad_path);
3836 if (!NT_STATUS_IS_OK(status)) {
3838 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION) &&
3841 * Yes, in the DOS error code case we get a
3842 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3843 * samba4 torture test.
3845 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3848 END_PROFILE(SMBmkdir);
3849 return ERROR_NT(status);
3852 if (lp_inherit_owner(SNUM(conn))) {
3853 /* Ensure we're checking for a symlink here.... */
3854 /* We don't want to get caught by a symlink racer. */
3856 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3857 END_PROFILE(SMBmkdir);
3858 return(UNIXERROR(ERRDOS,ERRnoaccess));
3861 if(!S_ISDIR(sbuf.st_mode)) {
3862 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3863 END_PROFILE(SMBmkdir);
3864 return(UNIXERROR(ERRDOS,ERRnoaccess));
3867 change_owner_to_parent(conn, NULL, directory, &sbuf);
3870 outsize = set_message(outbuf,0,0,False);
3872 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3874 END_PROFILE(SMBmkdir);
3878 /****************************************************************************
3879 Static function used by reply_rmdir to delete an entire directory
3880 tree recursively. Return False on ok, True on fail.
3881 ****************************************************************************/
3883 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3885 const char *dname = NULL;
3888 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3893 while((dname = ReadDirName(dir_hnd, &offset))) {
3897 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3900 if (!is_visible_file(conn, directory, dname, &st, False))
3903 /* Construct the full name. */
3904 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3910 pstrcpy(fullname, directory);
3911 pstrcat(fullname, "/");
3912 pstrcat(fullname, dname);
3914 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3919 if(st.st_mode & S_IFDIR) {
3920 if(recursive_rmdir(conn, fullname)!=0) {
3924 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3928 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3937 /****************************************************************************
3938 The internals of the rmdir code - called elsewhere.
3939 ****************************************************************************/
3941 BOOL rmdir_internals(connection_struct *conn, char *directory)
3946 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3947 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3949 * Check to see if the only thing in this directory are
3950 * vetoed files/directories. If so then delete them and
3951 * retry. If we fail to delete any of them (and we *don't*
3952 * do a recursive delete) then fail the rmdir.
3954 BOOL all_veto_files = True;
3956 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3958 if(dir_hnd != NULL) {
3960 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3961 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3963 if (!is_visible_file(conn, directory, dname, &st, False))
3965 if(!IS_VETO_PATH(conn, dname)) {
3966 all_veto_files = False;
3971 if(all_veto_files) {
3972 RewindDir(dir_hnd,&dirpos);
3973 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3976 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3978 if (!is_visible_file(conn, directory, dname, &st, False))
3981 /* Construct the full name. */
3982 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3987 pstrcpy(fullname, directory);
3988 pstrcat(fullname, "/");
3989 pstrcat(fullname, dname);
3991 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3993 if(st.st_mode & S_IFDIR) {
3994 if(lp_recursive_veto_delete(SNUM(conn))) {
3995 if(recursive_rmdir(conn, fullname) != 0)
3998 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4000 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4004 /* Retry the rmdir */
4005 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
4015 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
4020 /****************************************************************************
4022 ****************************************************************************/
4024 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4029 BOOL bad_path = False;
4030 SMB_STRUCT_STAT sbuf;
4032 START_PROFILE(SMBrmdir);
4034 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 END_PROFILE(SMBrmdir);
4037 return ERROR_NT(status);
4040 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
4042 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
4044 END_PROFILE(SMBrmdir);
4045 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4048 if (check_name(directory,conn)) {
4049 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4050 ok = rmdir_internals(conn, directory);
4054 END_PROFILE(SMBrmdir);
4055 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
4058 outsize = set_message(outbuf,0,0,False);
4060 DEBUG( 3, ( "rmdir %s\n", directory ) );
4062 END_PROFILE(SMBrmdir);
4066 /*******************************************************************
4067 Resolve wildcards in a filename rename.
4068 Note that name is in UNIX charset and thus potentially can be more
4069 than fstring buffer (255 bytes) especially in default UTF-8 case.
4070 Therefore, we use pstring inside and all calls should ensure that
4071 name2 is at least pstring-long (they do already)
4072 ********************************************************************/
4074 static BOOL resolve_wildcards(const char *name1, char *name2)
4076 pstring root1,root2;
4078 char *p,*p2, *pname1, *pname2;
4079 int available_space, actual_space;
4082 pname1 = strrchr_m(name1,'/');
4083 pname2 = strrchr_m(name2,'/');
4085 if (!pname1 || !pname2)
4088 pstrcpy(root1,pname1);
4089 pstrcpy(root2,pname2);
4090 p = strrchr_m(root1,'.');
4097 p = strrchr_m(root2,'.');
4111 } else if (*p2 == '*') {
4127 } else if (*p2 == '*') {
4137 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4140 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4141 if (actual_space >= available_space - 1) {
4142 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4143 actual_space - available_space));
4146 pstrcpy_base(pname2, root2, name2);
4152 /****************************************************************************
4153 Ensure open files have their names updated. Updated to notify other smbd's
4155 ****************************************************************************/
4157 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4158 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4161 BOOL did_rename = False;
4163 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4164 /* fsp_name is a relative path under the fsp. To change this for other
4165 sharepaths we need to manipulate relative paths. */
4166 /* TODO - create the absolute path and manipulate the newname
4167 relative to the sharepath. */
4168 if (fsp->conn != conn) {
4171 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4172 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4173 fsp->fsp_name, newname ));
4174 string_set(&fsp->fsp_name, newname);
4179 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4180 (unsigned int)dev, (double)inode, newname ));
4183 /* Send messages to all smbd's (not ourself) that the name has changed. */
4184 rename_share_filename(lck, conn->connectpath, newname);
4187 /****************************************************************************
4188 We need to check if the source path is a parent directory of the destination
4189 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4190 refuse the rename with a sharing violation. Under UNIX the above call can
4191 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4192 probably need to check that the client is a Windows one before disallowing
4193 this as a UNIX client (one with UNIX extensions) can know the source is a
4194 symlink and make this decision intelligently. Found by an excellent bug
4195 report from <AndyLiebman@aol.com>.
4196 ****************************************************************************/
4198 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4200 const char *psrc = src;
4201 const char *pdst = dest;
4204 if (psrc[0] == '.' && psrc[1] == '/') {
4207 if (pdst[0] == '.' && pdst[1] == '/') {
4210 if ((slen = strlen(psrc)) > strlen(pdst)) {
4213 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4216 /****************************************************************************
4217 Rename an open file - given an fsp.
4218 ****************************************************************************/
4220 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
4222 SMB_STRUCT_STAT sbuf;
4223 BOOL bad_path = False;
4224 pstring newname_last_component;
4225 NTSTATUS error = NT_STATUS_OK;
4228 struct share_mode_lock *lck = NULL;
4231 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
4233 /* Quick check for "." and ".." */
4234 if (!bad_path && newname_last_component[0] == '.') {
4235 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
4236 return NT_STATUS_ACCESS_DENIED;
4239 if (!rcdest && bad_path) {
4240 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4243 /* Ensure newname contains a '/' */
4244 if(strrchr_m(newname,'/') == 0) {
4247 pstrcpy(tmpstr, "./");
4248 pstrcat(tmpstr, newname);
4249 pstrcpy(newname, tmpstr);
4253 * Check for special case with case preserving and not
4254 * case sensitive. If the old last component differs from the original
4255 * last component only by case, then we should allow
4256 * the rename (user is trying to change the case of the
4260 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4261 strequal(newname, fsp->fsp_name)) {
4263 pstring newname_modified_last_component;
4266 * Get the last component of the modified name.
4267 * Note that we guarantee that newname contains a '/'
4270 p = strrchr_m(newname,'/');
4271 pstrcpy(newname_modified_last_component,p+1);
4273 if(strcsequal(newname_modified_last_component,
4274 newname_last_component) == False) {
4276 * Replace the modified last component with
4279 pstrcpy(p+1, newname_last_component);
4284 * If the src and dest names are identical - including case,
4285 * don't do the rename, just return success.
4288 if (strcsequal(fsp->fsp_name, newname)) {
4289 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4291 return NT_STATUS_OK;
4294 dest_exists = vfs_object_exist(conn,newname,NULL);
4296 if(!replace_if_exists && dest_exists) {
4297 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4298 fsp->fsp_name,newname));
4299 return NT_STATUS_OBJECT_NAME_COLLISION;
4302 error = can_rename(conn,newname,attrs,&sbuf);
4304 if (dest_exists && !NT_STATUS_IS_OK(error)) {
4305 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4306 nt_errstr(error), fsp->fsp_name,newname));
4307 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4308 error = NT_STATUS_ACCESS_DENIED;
4312 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4313 return NT_STATUS_ACCESS_DENIED;
4316 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4318 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4319 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4320 fsp->fsp_name,newname));
4321 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4323 return NT_STATUS_OK;
4328 if (errno == ENOTDIR || errno == EISDIR) {
4329 error = NT_STATUS_OBJECT_NAME_COLLISION;
4331 error = map_nt_error_from_unix(errno);
4334 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4335 nt_errstr(error), fsp->fsp_name,newname));
4340 /****************************************************************************
4341 The guts of the rename command, split out so it may be called by the NT SMB
4343 ****************************************************************************/
4345 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
4349 pstring last_component_src;
4350 pstring last_component_dest;
4352 BOOL bad_path_src = False;
4353 BOOL bad_path_dest = False;
4355 NTSTATUS error = NT_STATUS_OK;
4358 SMB_STRUCT_STAT sbuf1, sbuf2;
4359 struct share_mode_lock *lck = NULL;
4361 *directory = *mask = 0;
4366 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4367 if (!rc && bad_path_src) {
4368 if (ms_has_wild(last_component_src))
4369 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4370 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4373 /* Quick check for "." and ".." */
4374 if (last_component_src[0] == '.') {
4375 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4376 return NT_STATUS_OBJECT_NAME_INVALID;
4380 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4382 /* Quick check for "." and ".." */
4383 if (last_component_dest[0] == '.') {
4384 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4385 return NT_STATUS_OBJECT_NAME_INVALID;
4390 * Split the old name into directory and last component
4391 * strings. Note that unix_convert may have stripped off a
4392 * leading ./ from both name and newname if the rename is
4393 * at the root of the share. We need to make sure either both
4394 * name and newname contain a / character or neither of them do
4395 * as this is checked in resolve_wildcards().
4398 p = strrchr_m(name,'/');
4400 pstrcpy(directory,".");
4404 pstrcpy(directory,name);
4406 *p = '/'; /* Replace needed for exceptional test below. */
4410 * We should only check the mangled cache
4411 * here if unix_convert failed. This means
4412 * that the path in 'mask' doesn't exist
4413 * on the file system and so we need to look
4414 * for a possible mangle. This patch from
4415 * Tine Smukavec <valentin.smukavec@hermes.si>.
4418 if (!rc && mangle_is_mangled(mask, conn->params))
4419 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4423 * No wildcards - just process the one file.
4425 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4427 /* Add a terminating '/' to the directory name. */
4428 pstrcat(directory,"/");
4429 pstrcat(directory,mask);
4431 /* Ensure newname contains a '/' also */
4432 if(strrchr_m(newname,'/') == 0) {
4435 pstrcpy(tmpstr, "./");
4436 pstrcat(tmpstr, newname);
4437 pstrcpy(newname, tmpstr);
4440 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4441 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4442 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4443 newname, last_component_dest, is_short_name));
4446 * Check for special case with case preserving and not
4447 * case sensitive, if directory and newname are identical,
4448 * and the old last component differs from the original
4449 * last component only by case, then we should allow
4450 * the rename (user is trying to change the case of the
4453 if((conn->case_sensitive == False) &&
4454 (((conn->case_preserve == True) &&
4455 (is_short_name == False)) ||
4456 ((conn->short_case_preserve == True) &&
4457 (is_short_name == True))) &&
4458 strcsequal(directory, newname)) {
4459 pstring modified_last_component;
4462 * Get the last component of the modified name.
4463 * Note that we guarantee that newname contains a '/'
4466 p = strrchr_m(newname,'/');
4467 pstrcpy(modified_last_component,p+1);
4469 if(strcsequal(modified_last_component,
4470 last_component_dest) == False) {
4472 * Replace the modified last component with
4475 pstrcpy(p+1, last_component_dest);
4479 resolve_wildcards(directory,newname);
4482 * The source object must exist.
4485 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4486 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4487 directory,newname));
4489 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4491 * Must return different errors depending on whether the parent
4492 * directory existed or not.
4495 p = strrchr_m(directory, '/');
4497 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4499 if (vfs_object_exist(conn, directory, NULL))
4500 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4501 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4503 error = map_nt_error_from_unix(errno);
4504 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4505 nt_errstr(error), directory,newname));
4510 if (!rcdest && bad_path_dest) {
4511 if (ms_has_wild(last_component_dest))
4512 return NT_STATUS_OBJECT_NAME_INVALID;
4513 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4516 error = can_rename(conn,directory,attrs,&sbuf1);
4518 if (!NT_STATUS_IS_OK(error)) {
4519 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4520 nt_errstr(error), directory,newname));
4525 * If the src and dest names are identical - including case,
4526 * don't do the rename, just return success.
4529 if (strcsequal(directory, newname)) {
4530 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4531 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4532 return NT_STATUS_OK;
4535 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4536 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4537 directory,newname));
4538 return NT_STATUS_OBJECT_NAME_COLLISION;
4541 if (rename_path_prefix_equal(directory, newname)) {
4542 return NT_STATUS_SHARING_VIOLATION;
4545 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4547 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4548 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4549 directory,newname));
4550 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4552 return NT_STATUS_OK;
4556 if (errno == ENOTDIR || errno == EISDIR)
4557 error = NT_STATUS_OBJECT_NAME_COLLISION;
4559 error = map_nt_error_from_unix(errno);
4561 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4562 nt_errstr(error), directory,newname));
4567 * Wildcards - process each file that matches.
4569 struct smb_Dir *dir_hnd = NULL;
4573 if (strequal(mask,"????????.???"))
4576 if (check_name(directory,conn))
4577 dir_hnd = OpenDir(conn, directory, mask, attrs);
4581 error = NT_STATUS_NO_SUCH_FILE;
4582 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4584 while ((dname = ReadDirName(dir_hnd, &offset))) {
4586 BOOL sysdir_entry = False;
4588 pstrcpy(fname,dname);
4590 /* Quick check for "." and ".." */
4591 if (fname[0] == '.') {
4592 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4594 sysdir_entry = True;
4601 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4604 if(!mask_match(fname, mask, conn->case_sensitive))
4608 error = NT_STATUS_OBJECT_NAME_INVALID;
4612 error = NT_STATUS_ACCESS_DENIED;
4613 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4614 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4615 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4616 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4619 error = can_rename(conn,fname,attrs,&sbuf1);
4620 if (!NT_STATUS_IS_OK(error)) {
4621 DEBUG(6,("rename %s refused\n", fname));
4624 pstrcpy(destname,newname);
4626 if (!resolve_wildcards(fname,destname)) {
4627 DEBUG(6,("resolve_wildcards %s %s failed\n",
4632 if (strcsequal(fname,destname)) {
4633 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4634 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4636 error = NT_STATUS_OK;
4640 if (!replace_if_exists &&
4641 vfs_file_exist(conn,destname, NULL)) {
4642 DEBUG(6,("file_exist %s\n", destname));
4643 error = NT_STATUS_OBJECT_NAME_COLLISION;
4647 if (rename_path_prefix_equal(fname, destname)) {
4648 return NT_STATUS_SHARING_VIOLATION;
4651 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4653 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4654 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4656 error = NT_STATUS_OK;
4659 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4664 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4665 if (!rcdest && bad_path_dest) {
4666 if (ms_has_wild(last_component_dest))
4667 return NT_STATUS_OBJECT_NAME_INVALID;
4668 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4673 if (count == 0 && NT_STATUS_IS_OK(error)) {
4674 error = map_nt_error_from_unix(errno);
4680 /****************************************************************************
4682 ****************************************************************************/
4684 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4691 uint32 attrs = SVAL(inbuf,smb_vwv0);
4693 BOOL path_contains_wcard = False;
4695 START_PROFILE(SMBmv);
4697 p = smb_buf(inbuf) + 1;
4698 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
4699 if (!NT_STATUS_IS_OK(status)) {
4701 return ERROR_NT(status);
4704 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4705 if (!NT_STATUS_IS_OK(status)) {
4707 return ERROR_NT(status);
4710 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4711 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4713 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4715 status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard);
4716 if (!NT_STATUS_IS_OK(status)) {
4718 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4719 /* We have re-scheduled this call. */
4722 return ERROR_NT(status);
4726 * Win2k needs a changenotify request response before it will
4727 * update after a rename..
4729 process_pending_change_notify_queue((time_t)0);
4730 outsize = set_message(outbuf,0,0,False);
4736 /*******************************************************************
4737 Copy a file as part of a reply_copy.
4738 ******************************************************************/
4740 BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4741 int count,BOOL target_is_directory, int *err_ret)
4743 SMB_STRUCT_STAT src_sbuf, sbuf2;
4745 files_struct *fsp1,*fsp2;
4748 uint32 new_create_disposition;
4753 pstrcpy(dest,dest1);
4754 if (target_is_directory) {
4755 char *p = strrchr_m(src,'/');
4765 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4769 if (!target_is_directory && count) {
4770 new_create_disposition = FILE_OPEN;
4772 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4773 NULL, NULL, &new_create_disposition, NULL)) {
4778 status = open_file_ntcreate(conn,src,&src_sbuf,
4780 FILE_SHARE_READ|FILE_SHARE_WRITE,
4783 FILE_ATTRIBUTE_NORMAL,
4787 if (!NT_STATUS_IS_OK(status)) {
4791 dosattrs = dos_mode(conn, src, &src_sbuf);
4792 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4793 ZERO_STRUCTP(&sbuf2);
4796 status = open_file_ntcreate(conn,dest,&sbuf2,
4798 FILE_SHARE_READ|FILE_SHARE_WRITE,
4799 new_create_disposition,
4805 if (!NT_STATUS_IS_OK(status)) {
4806 close_file(fsp1,ERROR_CLOSE);
4810 if ((ofun&3) == 1) {
4811 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4812 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4814 * Stop the copy from occurring.
4817 src_sbuf.st_size = 0;
4821 if (src_sbuf.st_size) {
4822 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4825 close_file(fsp1,NORMAL_CLOSE);
4827 /* Ensure the modtime is set correctly on the destination file. */
4828 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4831 * As we are opening fsp1 read-only we only expect
4832 * an error on close on fsp2 if we are out of space.
4833 * Thus we don't look at the error return from the
4836 *err_ret = close_file(fsp2,NORMAL_CLOSE);
4838 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4841 /****************************************************************************
4842 Reply to a file copy.
4843 ****************************************************************************/
4845 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4850 pstring mask,newname;
4853 int error = ERRnoaccess;
4857 int tid2 = SVAL(inbuf,smb_vwv0);
4858 int ofun = SVAL(inbuf,smb_vwv1);
4859 int flags = SVAL(inbuf,smb_vwv2);
4860 BOOL target_is_directory=False;
4861 BOOL bad_path1 = False;
4862 BOOL bad_path2 = False;
4863 BOOL path_contains_wcard1 = False;
4864 BOOL path_contains_wcard2 = False;
4866 SMB_STRUCT_STAT sbuf1, sbuf2;
4868 START_PROFILE(SMBcopy);
4870 *directory = *mask = 0;
4873 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 END_PROFILE(SMBcopy);
4876 return ERROR_NT(status);
4878 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 END_PROFILE(SMBcopy);
4881 return ERROR_NT(status);
4884 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4886 if (tid2 != conn->cnum) {
4887 /* can't currently handle inter share copies XXXX */
4888 DEBUG(3,("Rejecting inter-share copy\n"));
4889 END_PROFILE(SMBcopy);
4890 return ERROR_DOS(ERRSRV,ERRinvdevice);
4893 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4894 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4896 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4897 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4899 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4901 if ((flags&1) && target_is_directory) {
4902 END_PROFILE(SMBcopy);
4903 return ERROR_DOS(ERRDOS,ERRbadfile);
4906 if ((flags&2) && !target_is_directory) {
4907 END_PROFILE(SMBcopy);
4908 return ERROR_DOS(ERRDOS,ERRbadpath);
4911 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4912 /* wants a tree copy! XXXX */
4913 DEBUG(3,("Rejecting tree copy\n"));
4914 END_PROFILE(SMBcopy);
4915 return ERROR_DOS(ERRSRV,ERRerror);
4918 p = strrchr_m(name,'/');
4920 pstrcpy(directory,"./");
4924 pstrcpy(directory,name);
4929 * We should only check the mangled cache
4930 * here if unix_convert failed. This means
4931 * that the path in 'mask' doesn't exist
4932 * on the file system and so we need to look
4933 * for a possible mangle. This patch from
4934 * Tine Smukavec <valentin.smukavec@hermes.si>.
4937 if (!rc && mangle_is_mangled(mask, conn->params))
4938 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4940 has_wild = path_contains_wcard1;
4943 pstrcat(directory,"/");
4944 pstrcat(directory,mask);
4945 if (resolve_wildcards(directory,newname) &&
4946 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4950 END_PROFILE(SMBcopy);
4951 return(UNIXERROR(ERRHRD,ERRgeneral));
4954 exists = vfs_file_exist(conn,directory,NULL);
4957 struct smb_Dir *dir_hnd = NULL;
4961 if (strequal(mask,"????????.???"))
4964 if (check_name(directory,conn))
4965 dir_hnd = OpenDir(conn, directory, mask, 0);
4971 while ((dname = ReadDirName(dir_hnd, &offset))) {
4973 pstrcpy(fname,dname);
4975 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4978 if(!mask_match(fname, mask, conn->case_sensitive))
4981 error = ERRnoaccess;
4982 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4983 pstrcpy(destname,newname);
4984 if (resolve_wildcards(fname,destname) &&
4985 copy_file(fname,destname,conn,ofun,
4986 count,target_is_directory,&err))
4988 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4996 /* Error on close... */
4998 END_PROFILE(SMBcopy);
4999 return(UNIXERROR(ERRHRD,ERRgeneral));
5003 END_PROFILE(SMBcopy);
5004 return ERROR_DOS(ERRDOS,error);
5006 if((errno == ENOENT) && (bad_path1 || bad_path2) &&
5008 /* Samba 3.0.22 has ERRDOS/ERRbadpath in the
5009 * DOS error code case
5011 return ERROR_DOS(ERRDOS, ERRbadpath);
5013 END_PROFILE(SMBcopy);
5014 return(UNIXERROR(ERRDOS,error));
5018 outsize = set_message(outbuf,1,0,True);
5019 SSVAL(outbuf,smb_vwv0,count);
5021 END_PROFILE(SMBcopy);
5025 /****************************************************************************
5027 ****************************************************************************/
5029 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5037 START_PROFILE(pathworks_setdir);
5040 if (!CAN_SETDIR(snum)) {
5041 END_PROFILE(pathworks_setdir);
5042 return ERROR_DOS(ERRDOS,ERRnoaccess);
5045 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5046 if (!NT_STATUS_IS_OK(status)) {
5047 END_PROFILE(pathworks_setdir);
5048 return ERROR_NT(status);
5051 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
5053 if (strlen(newdir) == 0) {
5056 ok = vfs_directory_exist(conn,newdir,NULL);
5058 set_conn_connectpath(conn,newdir);
5062 END_PROFILE(pathworks_setdir);
5063 return ERROR_DOS(ERRDOS,ERRbadpath);
5066 outsize = set_message(outbuf,0,0,False);
5067 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5069 DEBUG(3,("setdir %s\n", newdir));
5071 END_PROFILE(pathworks_setdir);
5076 #define DBGC_CLASS DBGC_LOCKING
5078 /****************************************************************************
5079 Get a lock pid, dealing with large count requests.
5080 ****************************************************************************/
5082 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5084 if(!large_file_format)
5085 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5087 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5090 /****************************************************************************
5091 Get a lock count, dealing with large count requests.
5092 ****************************************************************************/
5094 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5096 SMB_BIG_UINT count = 0;
5098 if(!large_file_format) {
5099 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5102 #if defined(HAVE_LONGLONG)
5103 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5104 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5105 #else /* HAVE_LONGLONG */
5108 * NT4.x seems to be broken in that it sends large file (64 bit)
5109 * lockingX calls even if the CAP_LARGE_FILES was *not*
5110 * negotiated. For boxes without large unsigned ints truncate the
5111 * lock count by dropping the top 32 bits.
5114 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5115 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5116 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5117 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5118 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5121 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5122 #endif /* HAVE_LONGLONG */
5128 #if !defined(HAVE_LONGLONG)
5129 /****************************************************************************
5130 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5131 ****************************************************************************/
5133 static uint32 map_lock_offset(uint32 high, uint32 low)
5137 uint32 highcopy = high;
5140 * Try and find out how many significant bits there are in high.
5143 for(i = 0; highcopy; i++)
5147 * We use 31 bits not 32 here as POSIX
5148 * lock offsets may not be negative.
5151 mask = (~0) << (31 - i);
5154 return 0; /* Fail. */
5160 #endif /* !defined(HAVE_LONGLONG) */
5162 /****************************************************************************
5163 Get a lock offset, dealing with large offset requests.
5164 ****************************************************************************/
5166 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5168 SMB_BIG_UINT offset = 0;
5172 if(!large_file_format) {
5173 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5176 #if defined(HAVE_LONGLONG)
5177 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5178 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5179 #else /* HAVE_LONGLONG */
5182 * NT4.x seems to be broken in that it sends large file (64 bit)
5183 * lockingX calls even if the CAP_LARGE_FILES was *not*
5184 * negotiated. For boxes without large unsigned ints mangle the
5185 * lock offset by mapping the top 32 bits onto the lower 32.
5188 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5189 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5190 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5193 if((new_low = map_lock_offset(high, low)) == 0) {
5195 return (SMB_BIG_UINT)-1;
5198 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5199 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5200 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5201 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5204 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5205 #endif /* HAVE_LONGLONG */
5211 /****************************************************************************
5212 Reply to a lockingX request.
5213 ****************************************************************************/
5215 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5216 int length, int bufsize)
5218 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5219 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5220 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5221 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5222 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5223 SMB_BIG_UINT count = 0, offset = 0;
5225 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5228 BOOL large_file_format =
5229 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5231 BOOL my_lock_ctx = False;
5232 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5234 START_PROFILE(SMBlockingX);
5236 CHECK_FSP(fsp,conn);
5238 data = smb_buf(inbuf);
5240 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5241 /* we don't support these - and CANCEL_LOCK makes w2k
5242 and XP reboot so I don't really want to be
5243 compatible! (tridge) */
5244 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5247 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5248 /* Need to make this like a cancel.... JRA. */
5249 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
5252 /* Check if this is an oplock break on a file
5253 we have granted an oplock on.
5255 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5256 /* Client can insist on breaking to none. */
5257 BOOL break_to_none = (oplocklevel == 0);
5260 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5261 "for fnum = %d\n", (unsigned int)oplocklevel,
5265 * Make sure we have granted an exclusive or batch oplock on
5269 if (fsp->oplock_type == 0) {
5271 /* The Samba4 nbench simulator doesn't understand
5272 the difference between break to level2 and break
5273 to none from level2 - it sends oplock break
5274 replies in both cases. Don't keep logging an error
5275 message here - just ignore it. JRA. */
5277 DEBUG(5,("reply_lockingX: Error : oplock break from "
5278 "client for fnum = %d (oplock=%d) and no "
5279 "oplock granted on this file (%s).\n",
5280 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5282 /* if this is a pure oplock break request then don't
5284 if (num_locks == 0 && num_ulocks == 0) {
5285 END_PROFILE(SMBlockingX);
5288 END_PROFILE(SMBlockingX);
5289 return ERROR_DOS(ERRDOS,ERRlock);
5293 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5295 result = remove_oplock(fsp);
5297 result = downgrade_oplock(fsp);
5301 DEBUG(0, ("reply_lockingX: error in removing "
5302 "oplock on file %s\n", fsp->fsp_name));
5303 /* Hmmm. Is this panic justified? */
5304 smb_panic("internal tdb error");
5307 reply_to_oplock_break_requests(fsp);
5309 /* if this is a pure oplock break request then don't send a
5311 if (num_locks == 0 && num_ulocks == 0) {
5312 /* Sanity check - ensure a pure oplock break is not a
5314 if(CVAL(inbuf,smb_vwv0) != 0xff)
5315 DEBUG(0,("reply_lockingX: Error : pure oplock "
5316 "break is a chained %d request !\n",
5317 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5318 END_PROFILE(SMBlockingX);
5324 * We do this check *after* we have checked this is not a oplock break
5325 * response message. JRA.
5328 release_level_2_oplocks_on_change(fsp);
5330 /* Data now points at the beginning of the list
5331 of smb_unlkrng structs */
5332 for(i = 0; i < (int)num_ulocks; i++) {
5333 lock_pid = get_lock_pid( data, i, large_file_format);
5334 count = get_lock_count( data, i, large_file_format);
5335 offset = get_lock_offset( data, i, large_file_format, &err);
5338 * There is no error code marked "stupid client bug".... :-).
5341 END_PROFILE(SMBlockingX);
5342 return ERROR_DOS(ERRDOS,ERRnoaccess);
5345 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5346 "pid %u, file %s\n", (double)offset, (double)count,
5347 (unsigned int)lock_pid, fsp->fsp_name ));
5349 status = do_unlock(fsp,
5355 if (NT_STATUS_V(status)) {
5356 END_PROFILE(SMBlockingX);
5357 return ERROR_NT(status);
5361 /* Setup the timeout in seconds. */
5363 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5365 /* Now do any requested locks */
5366 data += ((large_file_format ? 20 : 10)*num_ulocks);
5368 /* Data now points at the beginning of the list
5369 of smb_lkrng structs */
5371 for(i = 0; i < (int)num_locks; i++) {
5372 enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK);
5373 lock_pid = get_lock_pid( data, i, large_file_format);
5374 count = get_lock_count( data, i, large_file_format);
5375 offset = get_lock_offset( data, i, large_file_format, &err);
5378 * There is no error code marked "stupid client bug".... :-).
5381 END_PROFILE(SMBlockingX);
5382 return ERROR_DOS(ERRDOS,ERRnoaccess);
5385 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5386 "%u, file %s timeout = %d\n", (double)offset,
5387 (double)count, (unsigned int)lock_pid,
5388 fsp->fsp_name, (int)lock_timeout ));
5390 status = do_lock_spin(fsp,
5398 if (NT_STATUS_V(status)) {
5400 * Interesting fact found by IFSTEST /t
5401 * LockOverlappedTest... Even if it's our own lock
5402 * context, we need to wait here as there may be an
5403 * unlock on the way. So I removed a "&&
5404 * !my_lock_ctx" from the following if statement. JRA.
5406 if ((lock_timeout != 0) &&
5407 lp_blocking_locks(SNUM(conn)) &&
5408 ERROR_WAS_LOCK_DENIED(status)) {
5410 * A blocking lock was requested. Package up
5411 * this smb into a queued request and push it
5412 * onto the blocking lock queue.
5414 if(push_blocking_lock_request(inbuf, length,
5423 END_PROFILE(SMBlockingX);
5431 /* If any of the above locks failed, then we must unlock
5432 all of the previous locks (X/Open spec). */
5433 if (i != num_locks && num_locks != 0) {
5435 * Ensure we don't do a remove on the lock that just failed,
5436 * as under POSIX rules, if we have a lock already there, we
5437 * will delete it (and we shouldn't) .....
5439 for(i--; i >= 0; i--) {
5440 lock_pid = get_lock_pid( data, i, large_file_format);
5441 count = get_lock_count( data, i, large_file_format);
5442 offset = get_lock_offset( data, i, large_file_format,
5446 * There is no error code marked "stupid client
5450 END_PROFILE(SMBlockingX);
5451 return ERROR_DOS(ERRDOS,ERRnoaccess);
5460 END_PROFILE(SMBlockingX);
5461 return ERROR_NT(status);
5464 set_message(outbuf,2,0,True);
5466 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5467 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5469 END_PROFILE(SMBlockingX);
5470 return chain_reply(inbuf,outbuf,length,bufsize);
5474 #define DBGC_CLASS DBGC_ALL
5476 /****************************************************************************
5477 Reply to a SMBreadbmpx (read block multiplex) request.
5478 ****************************************************************************/
5480 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5491 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5492 START_PROFILE(SMBreadBmpx);
5494 /* this function doesn't seem to work - disable by default */
5495 if (!lp_readbmpx()) {
5496 END_PROFILE(SMBreadBmpx);
5497 return ERROR_DOS(ERRSRV,ERRuseSTD);
5500 outsize = set_message(outbuf,8,0,True);
5502 CHECK_FSP(fsp,conn);
5503 if (!CHECK_READ(fsp,inbuf)) {
5504 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5507 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5508 maxcount = SVAL(inbuf,smb_vwv3);
5510 data = smb_buf(outbuf);
5511 pad = ((long)data)%4;
5516 max_per_packet = bufsize-(outsize+pad);
5520 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5521 END_PROFILE(SMBreadBmpx);
5522 return ERROR_DOS(ERRDOS,ERRlock);
5526 size_t N = MIN(max_per_packet,tcount-total_read);
5528 nread = read_file(fsp,data,startpos,N);
5533 if (nread < (ssize_t)N)
5534 tcount = total_read + nread;
5536 set_message(outbuf,8,nread+pad,False);
5537 SIVAL(outbuf,smb_vwv0,startpos);
5538 SSVAL(outbuf,smb_vwv2,tcount);
5539 SSVAL(outbuf,smb_vwv6,nread);
5540 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5543 if (!send_smb(smbd_server_fd(),outbuf))
5544 exit_server("reply_readbmpx: send_smb failed.");
5546 total_read += nread;
5548 } while (total_read < (ssize_t)tcount);
5550 END_PROFILE(SMBreadBmpx);
5554 /****************************************************************************
5555 Reply to a SMBsetattrE.
5556 ****************************************************************************/
5558 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5560 struct utimbuf unix_times;
5562 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5563 START_PROFILE(SMBsetattrE);
5565 outsize = set_message(outbuf,0,0,False);
5567 if(!fsp || (fsp->conn != conn)) {
5568 END_PROFILE(SMBsetattrE);
5569 return ERROR_DOS(ERRDOS,ERRbadfid);
5573 * Convert the DOS times into unix times. Ignore create
5574 * time as UNIX can't set this.
5577 unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
5578 unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
5581 * Patch from Ray Frush <frush@engr.colostate.edu>
5582 * Sometimes times are sent as zero - ignore them.
5585 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5586 /* Ignore request */
5587 if( DEBUGLVL( 3 ) ) {
5588 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5589 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5591 END_PROFILE(SMBsetattrE);
5593 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5594 /* set modify time = to access time if modify time was unset */
5595 unix_times.modtime = unix_times.actime;
5598 /* Set the date on this file */
5599 /* Should we set pending modtime here ? JRA */
5600 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5601 END_PROFILE(SMBsetattrE);
5602 return ERROR_DOS(ERRDOS,ERRnoaccess);
5605 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5606 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5608 END_PROFILE(SMBsetattrE);
5613 /* Back from the dead for OS/2..... JRA. */
5615 /****************************************************************************
5616 Reply to a SMBwritebmpx (write block multiplex primary) request.
5617 ****************************************************************************/
5619 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5622 ssize_t nwritten = -1;
5629 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5630 START_PROFILE(SMBwriteBmpx);
5632 CHECK_FSP(fsp,conn);
5633 if (!CHECK_WRITE(fsp)) {
5634 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5636 if (HAS_CACHED_ERROR(fsp)) {
5637 return(CACHED_ERROR(fsp));
5640 tcount = SVAL(inbuf,smb_vwv1);
5641 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5642 write_through = BITSETW(inbuf+smb_vwv7,0);
5643 numtowrite = SVAL(inbuf,smb_vwv10);
5644 smb_doff = SVAL(inbuf,smb_vwv11);
5646 data = smb_base(inbuf) + smb_doff;
5648 /* If this fails we need to send an SMBwriteC response,
5649 not an SMBwritebmpx - set this up now so we don't forget */
5650 SCVAL(outbuf,smb_com,SMBwritec);
5652 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5653 END_PROFILE(SMBwriteBmpx);
5654 return(ERROR_DOS(ERRDOS,ERRlock));
5657 nwritten = write_file(fsp,data,startpos,numtowrite);
5659 sync_file(conn, fsp, write_through);
5661 if(nwritten < (ssize_t)numtowrite) {
5662 END_PROFILE(SMBwriteBmpx);
5663 return(UNIXERROR(ERRHRD,ERRdiskfull));
5666 /* If the maximum to be written to this file
5667 is greater than what we just wrote then set
5668 up a secondary struct to be attached to this
5669 fd, we will use this to cache error messages etc. */
5671 if((ssize_t)tcount > nwritten) {
5672 write_bmpx_struct *wbms;
5673 if(fsp->wbmpx_ptr != NULL)
5674 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5676 wbms = SMB_MALLOC_P(write_bmpx_struct);
5678 DEBUG(0,("Out of memory in reply_readmpx\n"));
5679 END_PROFILE(SMBwriteBmpx);
5680 return(ERROR_DOS(ERRSRV,ERRnoresource));
5682 wbms->wr_mode = write_through;
5683 wbms->wr_discard = False; /* No errors yet */
5684 wbms->wr_total_written = nwritten;
5685 wbms->wr_errclass = 0;
5687 fsp->wbmpx_ptr = wbms;
5690 /* We are returning successfully, set the message type back to
5692 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5694 outsize = set_message(outbuf,1,0,True);
5696 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5698 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5699 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5701 if (write_through && tcount==nwritten) {
5702 /* We need to send both a primary and a secondary response */
5703 smb_setlen(outbuf,outsize - 4);
5705 if (!send_smb(smbd_server_fd(),outbuf))
5706 exit_server("reply_writebmpx: send_smb failed.");
5708 /* Now the secondary */
5709 outsize = set_message(outbuf,1,0,True);
5710 SCVAL(outbuf,smb_com,SMBwritec);
5711 SSVAL(outbuf,smb_vwv0,nwritten);
5714 END_PROFILE(SMBwriteBmpx);
5718 /****************************************************************************
5719 Reply to a SMBwritebs (write block multiplex secondary) request.
5720 ****************************************************************************/
5722 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5725 ssize_t nwritten = -1;
5732 write_bmpx_struct *wbms;
5733 BOOL send_response = False;
5734 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5735 START_PROFILE(SMBwriteBs);
5737 CHECK_FSP(fsp,conn);
5738 if (!CHECK_WRITE(fsp)) {
5739 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5742 tcount = SVAL(inbuf,smb_vwv1);
5743 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5744 numtowrite = SVAL(inbuf,smb_vwv6);
5745 smb_doff = SVAL(inbuf,smb_vwv7);
5747 data = smb_base(inbuf) + smb_doff;
5749 /* We need to send an SMBwriteC response, not an SMBwritebs */
5750 SCVAL(outbuf,smb_com,SMBwritec);
5752 /* This fd should have an auxiliary struct attached,
5753 check that it does */
5754 wbms = fsp->wbmpx_ptr;
5756 END_PROFILE(SMBwriteBs);
5760 /* If write through is set we can return errors, else we must cache them */
5761 write_through = wbms->wr_mode;
5763 /* Check for an earlier error */
5764 if(wbms->wr_discard) {
5765 END_PROFILE(SMBwriteBs);
5766 return -1; /* Just discard the packet */
5769 nwritten = write_file(fsp,data,startpos,numtowrite);
5771 sync_file(conn, fsp, write_through);
5773 if (nwritten < (ssize_t)numtowrite) {
5775 /* We are returning an error - we can delete the aux struct */
5778 fsp->wbmpx_ptr = NULL;
5779 END_PROFILE(SMBwriteBs);
5780 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5782 wbms->wr_errclass = ERRHRD;
5783 wbms->wr_error = ERRdiskfull;
5784 wbms->wr_status = NT_STATUS_DISK_FULL;
5785 wbms->wr_discard = True;
5786 END_PROFILE(SMBwriteBs);
5790 /* Increment the total written, if this matches tcount
5791 we can discard the auxiliary struct (hurrah !) and return a writeC */
5792 wbms->wr_total_written += nwritten;
5793 if(wbms->wr_total_written >= tcount) {
5794 if (write_through) {
5795 outsize = set_message(outbuf,1,0,True);
5796 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5797 send_response = True;
5801 fsp->wbmpx_ptr = NULL;
5805 END_PROFILE(SMBwriteBs);
5809 END_PROFILE(SMBwriteBs);
5813 /****************************************************************************
5814 Reply to a SMBgetattrE.
5815 ****************************************************************************/
5817 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5819 SMB_STRUCT_STAT sbuf;
5822 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5823 START_PROFILE(SMBgetattrE);
5825 outsize = set_message(outbuf,11,0,True);
5827 if(!fsp || (fsp->conn != conn)) {
5828 END_PROFILE(SMBgetattrE);
5829 return ERROR_DOS(ERRDOS,ERRbadfid);
5832 /* Do an fstat on this file */
5833 if(fsp_stat(fsp, &sbuf)) {
5834 END_PROFILE(SMBgetattrE);
5835 return(UNIXERROR(ERRDOS,ERRnoaccess));
5838 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5841 * Convert the times into dos times. Set create
5842 * date to be last modify date as UNIX doesn't save
5846 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5847 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5848 /* Should we check pending modtime here ? JRA */
5849 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5852 SIVAL(outbuf,smb_vwv6,0);
5853 SIVAL(outbuf,smb_vwv8,0);
5855 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5856 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5857 SIVAL(outbuf,smb_vwv8,allocation_size);
5859 SSVAL(outbuf,smb_vwv10, mode);
5861 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5863 END_PROFILE(SMBgetattrE);