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);
433 /****************************************************************************
434 Pull a string and check the path - provide for error return.
435 ****************************************************************************/
437 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
440 char *tmppath_ptr = tmppath;
443 SMB_ASSERT(dest_len == sizeof(pstring));
447 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
449 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
451 if (lp_posix_pathnames()) {
452 *err = check_path_syntax_posix(dest, tmppath);
454 *err = check_path_syntax(dest, tmppath);
459 /****************************************************************************
460 Reply to a special message.
461 ****************************************************************************/
463 int reply_special(char *inbuf,char *outbuf)
466 int msg_type = CVAL(inbuf,0);
467 int msg_flags = CVAL(inbuf,1);
471 static BOOL already_got_session = False;
475 memset(outbuf,'\0',smb_size);
477 smb_setlen(outbuf,0);
480 case 0x81: /* session request */
482 if (already_got_session) {
483 exit_server("multiple session request not permitted");
486 SCVAL(outbuf,0,0x82);
488 if (name_len(inbuf+4) > 50 ||
489 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
490 DEBUG(0,("Invalid name length in session request\n"));
493 name_extract(inbuf,4,name1);
494 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
495 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
498 set_local_machine_name(name1, True);
499 set_remote_machine_name(name2, True);
501 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
502 get_local_machine_name(), get_remote_machine_name(),
505 if (name_type == 'R') {
506 /* We are being asked for a pathworks session ---
508 SCVAL(outbuf, 0,0x83);
512 /* only add the client's machine name to the list
513 of possibly valid usernames if we are operating
514 in share mode security */
515 if (lp_security() == SEC_SHARE) {
516 add_session_user(get_remote_machine_name());
519 reload_services(True);
522 already_got_session = True;
525 case 0x89: /* session keepalive request
526 (some old clients produce this?) */
527 SCVAL(outbuf,0,SMBkeepalive);
531 case 0x82: /* positive session response */
532 case 0x83: /* negative session response */
533 case 0x84: /* retarget session response */
534 DEBUG(0,("Unexpected session response\n"));
537 case SMBkeepalive: /* session keepalive */
542 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
543 msg_type, msg_flags));
548 /****************************************************************************
550 ****************************************************************************/
552 int reply_tcon(connection_struct *conn,
553 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
560 uint16 vuid = SVAL(inbuf,smb_uid);
564 DATA_BLOB password_blob;
566 START_PROFILE(SMBtcon);
568 *service_buf = *password = *dev = 0;
570 p = smb_buf(inbuf)+1;
571 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
572 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
574 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
576 p = strrchr_m(service_buf,'\\');
580 service = service_buf;
583 password_blob = data_blob(password, pwlen+1);
585 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
587 data_blob_clear_free(&password_blob);
590 END_PROFILE(SMBtcon);
591 return ERROR_NT(nt_status);
594 outsize = set_message(outbuf,2,0,True);
595 SSVAL(outbuf,smb_vwv0,max_recv);
596 SSVAL(outbuf,smb_vwv1,conn->cnum);
597 SSVAL(outbuf,smb_tid,conn->cnum);
599 DEBUG(3,("tcon service=%s cnum=%d\n",
600 service, conn->cnum));
602 END_PROFILE(SMBtcon);
606 /****************************************************************************
607 Reply to a tcon and X.
608 ****************************************************************************/
610 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
615 /* what the cleint thinks the device is */
616 fstring client_devicetype;
617 /* what the server tells the client the share represents */
618 const char *server_devicetype;
620 uint16 vuid = SVAL(inbuf,smb_uid);
621 int passlen = SVAL(inbuf,smb_vwv3);
625 START_PROFILE(SMBtconX);
627 *service = *client_devicetype = 0;
629 /* we might have to close an old one */
630 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
631 close_cnum(conn,vuid);
634 if (passlen > MAX_PASS_LEN) {
635 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
638 if (global_encrypted_passwords_negotiated) {
639 password = data_blob(smb_buf(inbuf),passlen);
641 password = data_blob(smb_buf(inbuf),passlen+1);
642 /* Ensure correct termination */
643 password.data[passlen]=0;
646 p = smb_buf(inbuf) + passlen;
647 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
650 * the service name can be either: \\server\share
651 * or share directly like on the DELL PowerVault 705
654 q = strchr_m(path+2,'\\');
656 END_PROFILE(SMBtconX);
657 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
659 fstrcpy(service,q+1);
662 fstrcpy(service,path);
664 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
666 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
668 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
670 data_blob_clear_free(&password);
673 END_PROFILE(SMBtconX);
674 return ERROR_NT(nt_status);
678 server_devicetype = "IPC";
679 else if ( IS_PRINT(conn) )
680 server_devicetype = "LPT1:";
682 server_devicetype = "A:";
684 if (Protocol < PROTOCOL_NT1) {
685 set_message(outbuf,2,0,True);
687 p += srvstr_push(outbuf, p, server_devicetype, -1,
688 STR_TERMINATE|STR_ASCII);
689 set_message_end(outbuf,p);
691 /* NT sets the fstype of IPC$ to the null string */
692 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
694 set_message(outbuf,3,0,True);
697 p += srvstr_push(outbuf, p, server_devicetype, -1,
698 STR_TERMINATE|STR_ASCII);
699 p += srvstr_push(outbuf, p, fstype, -1,
702 set_message_end(outbuf,p);
704 /* what does setting this bit do? It is set by NT4 and
705 may affect the ability to autorun mounted cdroms */
706 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
707 (lp_csc_policy(SNUM(conn)) << 2));
709 init_dfsroot(conn, inbuf, outbuf);
713 DEBUG(3,("tconX service=%s \n",
716 /* set the incoming and outgoing tid to the just created one */
717 SSVAL(inbuf,smb_tid,conn->cnum);
718 SSVAL(outbuf,smb_tid,conn->cnum);
720 END_PROFILE(SMBtconX);
721 return chain_reply(inbuf,outbuf,length,bufsize);
724 /****************************************************************************
725 Reply to an unknown type.
726 ****************************************************************************/
728 int reply_unknown(char *inbuf,char *outbuf)
731 type = CVAL(inbuf,smb_com);
733 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
734 smb_fn_name(type), type, type));
736 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
739 /****************************************************************************
741 ****************************************************************************/
743 int reply_ioctl(connection_struct *conn,
744 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
746 uint16 device = SVAL(inbuf,smb_vwv1);
747 uint16 function = SVAL(inbuf,smb_vwv2);
748 uint32 ioctl_code = (device << 16) + function;
749 int replysize, outsize;
751 START_PROFILE(SMBioctl);
753 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
755 switch (ioctl_code) {
756 case IOCTL_QUERY_JOB_INFO:
760 END_PROFILE(SMBioctl);
761 return(ERROR_DOS(ERRSRV,ERRnosupport));
764 outsize = set_message(outbuf,8,replysize+1,True);
765 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
766 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
767 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
768 p = smb_buf(outbuf) + 1; /* Allow for alignment */
770 switch (ioctl_code) {
771 case IOCTL_QUERY_JOB_INFO:
773 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
775 END_PROFILE(SMBioctl);
776 return(UNIXERROR(ERRDOS,ERRbadfid));
778 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
779 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
781 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
787 END_PROFILE(SMBioctl);
791 /****************************************************************************
793 ****************************************************************************/
795 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
800 BOOL bad_path = False;
801 SMB_STRUCT_STAT sbuf;
804 START_PROFILE(SMBchkpth);
806 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
807 if (!NT_STATUS_IS_OK(status)) {
808 END_PROFILE(SMBchkpth);
809 return ERROR_NT(status);
812 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
814 unix_convert(name,conn,0,&bad_path,&sbuf);
816 END_PROFILE(SMBchkpth);
817 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
820 if (check_name(name,conn)) {
821 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
822 if (!(ok = S_ISDIR(sbuf.st_mode))) {
823 END_PROFILE(SMBchkpth);
824 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
829 /* We special case this - as when a Windows machine
830 is parsing a path is steps through the components
831 one at a time - if a component fails it expects
832 ERRbadpath, not ERRbadfile.
834 if(errno == ENOENT) {
836 * Windows returns different error codes if
837 * the parent directory is valid but not the
838 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
839 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
840 * if the path is invalid. This is different from set_bad_path_error()
841 * in the non-NT error case.
843 END_PROFILE(SMBchkpth);
844 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
847 END_PROFILE(SMBchkpth);
848 return(UNIXERROR(ERRDOS,ERRbadpath));
851 outsize = set_message(outbuf,0,0,False);
852 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
854 END_PROFILE(SMBchkpth);
858 /****************************************************************************
860 ****************************************************************************/
862 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
866 SMB_STRUCT_STAT sbuf;
871 BOOL bad_path = False;
875 START_PROFILE(SMBgetatr);
877 p = smb_buf(inbuf) + 1;
878 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
879 if (!NT_STATUS_IS_OK(status)) {
880 END_PROFILE(SMBgetatr);
881 return ERROR_NT(status);
884 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
886 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
887 under WfWg - weird! */
889 mode = aHIDDEN | aDIR;
890 if (!CAN_WRITE(conn))
896 unix_convert(fname,conn,0,&bad_path,&sbuf);
898 END_PROFILE(SMBgetatr);
899 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
901 if (check_name(fname,conn)) {
902 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
903 mode = dos_mode(conn,fname,&sbuf);
905 mtime = sbuf.st_mtime;
910 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
916 END_PROFILE(SMBgetatr);
917 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
920 outsize = set_message(outbuf,10,0,True);
922 SSVAL(outbuf,smb_vwv0,mode);
923 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
924 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
926 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
928 SIVAL(outbuf,smb_vwv3,(uint32)size);
930 if (Protocol >= PROTOCOL_NT1) {
931 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
934 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
936 END_PROFILE(SMBgetatr);
940 /****************************************************************************
942 ****************************************************************************/
944 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
951 SMB_STRUCT_STAT sbuf;
952 BOOL bad_path = False;
956 START_PROFILE(SMBsetatr);
958 p = smb_buf(inbuf) + 1;
959 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
960 if (!NT_STATUS_IS_OK(status)) {
961 END_PROFILE(SMBsetatr);
962 return ERROR_NT(status);
965 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
967 unix_convert(fname,conn,0,&bad_path,&sbuf);
969 END_PROFILE(SMBsetatr);
970 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
973 mode = SVAL(inbuf,smb_vwv0);
974 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
976 if (mode != FILE_ATTRIBUTE_NORMAL) {
977 if (VALID_STAT_OF_DIR(sbuf))
982 if (check_name(fname,conn)) {
983 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
990 ok = set_filetime(conn,fname,mtime);
993 END_PROFILE(SMBsetatr);
994 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
997 outsize = set_message(outbuf,0,0,False);
999 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1001 END_PROFILE(SMBsetatr);
1005 /****************************************************************************
1007 ****************************************************************************/
1009 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1012 SMB_BIG_UINT dfree,dsize,bsize;
1013 START_PROFILE(SMBdskattr);
1015 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1016 END_PROFILE(SMBdskattr);
1017 return(UNIXERROR(ERRHRD,ERRgeneral));
1020 outsize = set_message(outbuf,5,0,True);
1022 if (Protocol <= PROTOCOL_LANMAN2) {
1023 double total_space, free_space;
1024 /* we need to scale this to a number that DOS6 can handle. We
1025 use floating point so we can handle large drives on systems
1026 that don't have 64 bit integers
1028 we end up displaying a maximum of 2G to DOS systems
1030 total_space = dsize * (double)bsize;
1031 free_space = dfree * (double)bsize;
1033 dsize = (total_space+63*512) / (64*512);
1034 dfree = (free_space+63*512) / (64*512);
1036 if (dsize > 0xFFFF) dsize = 0xFFFF;
1037 if (dfree > 0xFFFF) dfree = 0xFFFF;
1039 SSVAL(outbuf,smb_vwv0,dsize);
1040 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1041 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1042 SSVAL(outbuf,smb_vwv3,dfree);
1044 SSVAL(outbuf,smb_vwv0,dsize);
1045 SSVAL(outbuf,smb_vwv1,bsize/512);
1046 SSVAL(outbuf,smb_vwv2,512);
1047 SSVAL(outbuf,smb_vwv3,dfree);
1050 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1052 END_PROFILE(SMBdskattr);
1056 /****************************************************************************
1058 Can be called from SMBsearch, SMBffirst or SMBfunique.
1059 ****************************************************************************/
1061 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1071 unsigned int numentries = 0;
1072 unsigned int maxentries = 0;
1073 BOOL finished = False;
1080 BOOL check_descend = False;
1081 BOOL expect_close = False;
1082 BOOL can_open = True;
1083 BOOL bad_path = False;
1085 BOOL mask_contains_wcard = False;
1086 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1088 START_PROFILE(SMBsearch);
1090 if (lp_posix_pathnames()) {
1091 END_PROFILE(SMBsearch);
1092 return reply_unknown(inbuf, outbuf);
1095 *mask = *directory = *fname = 0;
1097 /* If we were called as SMBffirst then we must expect close. */
1098 if(CVAL(inbuf,smb_com) == SMBffirst)
1099 expect_close = True;
1101 outsize = set_message(outbuf,1,3,True);
1102 maxentries = SVAL(inbuf,smb_vwv0);
1103 dirtype = SVAL(inbuf,smb_vwv1);
1104 p = smb_buf(inbuf) + 1;
1105 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1106 if (!NT_STATUS_IS_OK(nt_status)) {
1107 END_PROFILE(SMBsearch);
1108 return ERROR_NT(nt_status);
1111 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
1114 status_len = SVAL(p, 0);
1117 /* dirtype &= ~aDIR; */
1119 if (status_len == 0) {
1120 SMB_STRUCT_STAT sbuf;
1123 pstrcpy(directory,path);
1125 unix_convert(directory,conn,0,&bad_path,&sbuf);
1128 if (!check_name(directory,conn))
1131 p = strrchr_m(dir2,'/');
1140 p = strrchr_m(directory,'/');
1146 if (strlen(directory) == 0)
1147 pstrcpy(directory,".");
1148 memset((char *)status,'\0',21);
1149 SCVAL(status,0,(dirtype & 0x1F));
1153 memcpy(status,p,21);
1154 status_dirtype = CVAL(status,0) & 0x1F;
1155 if (status_dirtype != (dirtype & 0x1F))
1156 dirtype = status_dirtype;
1158 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1161 string_set(&conn->dirpath,dptr_path(dptr_num));
1162 pstrcpy(mask, dptr_wcard(dptr_num));
1166 p = smb_buf(outbuf) + 3;
1169 if (status_len == 0) {
1170 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1172 if(dptr_num == -2) {
1173 END_PROFILE(SMBsearch);
1174 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1176 END_PROFILE(SMBsearch);
1177 return ERROR_DOS(ERRDOS,ERRnofids);
1180 dirtype = dptr_attr(dptr_num);
1183 DEBUG(4,("dptr_num is %d\n",dptr_num));
1186 if ((dirtype&0x1F) == aVOLID) {
1187 memcpy(p,status,21);
1188 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1189 0,aVOLID,0,!allow_long_path_components);
1190 dptr_fill(p+12,dptr_num);
1191 if (dptr_zero(p+12) && (status_len==0))
1195 p += DIR_STRUCT_SIZE;
1198 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1200 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1201 conn->dirpath,lp_dontdescend(SNUM(conn))));
1202 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1203 check_descend = True;
1205 for (i=numentries;(i<maxentries) && !finished;i++) {
1206 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1208 memcpy(p,status,21);
1209 make_dir_struct(p,mask,fname,size, mode,date,
1210 !allow_long_path_components);
1211 if (!dptr_fill(p+12,dptr_num)) {
1215 p += DIR_STRUCT_SIZE;
1225 /* If we were called as SMBffirst with smb_search_id == NULL
1226 and no entries were found then return error and close dirptr
1229 if (numentries == 0 || !ok) {
1230 dptr_close(&dptr_num);
1231 } else if(ok && expect_close && status_len == 0) {
1232 /* Close the dptr - we know it's gone */
1233 dptr_close(&dptr_num);
1236 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1237 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1238 dptr_close(&dptr_num);
1241 if ((numentries == 0) && !mask_contains_wcard) {
1242 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1245 SSVAL(outbuf,smb_vwv0,numentries);
1246 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1247 SCVAL(smb_buf(outbuf),0,5);
1248 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1250 /* The replies here are never long name. */
1251 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1252 if (!allow_long_path_components) {
1253 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1256 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1257 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1259 outsize += DIR_STRUCT_SIZE*numentries;
1260 smb_setlen(outbuf,outsize - 4);
1262 if ((! *directory) && dptr_path(dptr_num))
1263 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1265 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1266 smb_fn_name(CVAL(inbuf,smb_com)),
1267 mask, directory, dirtype, numentries, maxentries ) );
1269 END_PROFILE(SMBsearch);
1273 /****************************************************************************
1274 Reply to a fclose (stop directory search).
1275 ****************************************************************************/
1277 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1286 BOOL path_contains_wcard = False;
1288 START_PROFILE(SMBfclose);
1290 if (lp_posix_pathnames()) {
1291 END_PROFILE(SMBfclose);
1292 return reply_unknown(inbuf, outbuf);
1295 outsize = set_message(outbuf,1,0,True);
1296 p = smb_buf(inbuf) + 1;
1297 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1298 if (!NT_STATUS_IS_OK(err)) {
1299 END_PROFILE(SMBfclose);
1300 return ERROR_NT(err);
1303 status_len = SVAL(p,0);
1306 if (status_len == 0) {
1307 END_PROFILE(SMBfclose);
1308 return ERROR_DOS(ERRSRV,ERRsrverror);
1311 memcpy(status,p,21);
1313 if(dptr_fetch(status+12,&dptr_num)) {
1314 /* Close the dptr - we know it's gone */
1315 dptr_close(&dptr_num);
1318 SSVAL(outbuf,smb_vwv0,0);
1320 DEBUG(3,("search close\n"));
1322 END_PROFILE(SMBfclose);
1326 /****************************************************************************
1328 ****************************************************************************/
1330 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1338 SMB_STRUCT_STAT sbuf;
1339 BOOL bad_path = False;
1341 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1343 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1346 uint32 create_disposition;
1347 uint32 create_options = 0;
1349 START_PROFILE(SMBopen);
1351 deny_mode = SVAL(inbuf,smb_vwv0);
1353 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 END_PROFILE(SMBopen);
1356 return ERROR_NT(status);
1359 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1361 unix_convert(fname,conn,0,&bad_path,&sbuf);
1363 END_PROFILE(SMBopen);
1364 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1367 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1368 &access_mask, &share_mode, &create_disposition, &create_options)) {
1369 END_PROFILE(SMBopen);
1370 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1373 fsp = open_file_ntcreate(conn,fname,&sbuf,
1383 END_PROFILE(SMBopen);
1384 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1385 /* We have re-scheduled this call. */
1388 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1391 size = sbuf.st_size;
1392 fattr = dos_mode(conn,fname,&sbuf);
1393 mtime = sbuf.st_mtime;
1396 DEBUG(3,("attempt to open a directory %s\n",fname));
1397 close_file(fsp,ERROR_CLOSE);
1398 END_PROFILE(SMBopen);
1399 return ERROR_DOS(ERRDOS,ERRnoaccess);
1402 outsize = set_message(outbuf,7,0,True);
1403 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1404 SSVAL(outbuf,smb_vwv1,fattr);
1405 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1406 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1408 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1410 SIVAL(outbuf,smb_vwv4,(uint32)size);
1411 SSVAL(outbuf,smb_vwv6,deny_mode);
1413 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1414 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1417 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1418 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1420 END_PROFILE(SMBopen);
1424 /****************************************************************************
1425 Reply to an open and X.
1426 ****************************************************************************/
1428 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1431 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1432 int deny_mode = SVAL(inbuf,smb_vwv3);
1433 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1434 /* Breakout the oplock request bits so we can set the
1435 reply bits separately. */
1436 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1437 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1438 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1440 int smb_sattr = SVAL(inbuf,smb_vwv4);
1441 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1443 int smb_ofun = SVAL(inbuf,smb_vwv8);
1447 SMB_STRUCT_STAT sbuf;
1449 BOOL bad_path = False;
1452 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1453 ssize_t retval = -1;
1456 uint32 create_disposition;
1457 uint32 create_options = 0;
1459 START_PROFILE(SMBopenX);
1461 /* If it's an IPC, pass off the pipe handler. */
1463 if (lp_nt_pipe_support()) {
1464 END_PROFILE(SMBopenX);
1465 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1467 END_PROFILE(SMBopenX);
1468 return ERROR_DOS(ERRSRV,ERRaccess);
1472 /* XXXX we need to handle passed times, sattr and flags */
1473 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1474 if (!NT_STATUS_IS_OK(status)) {
1475 END_PROFILE(SMBopenX);
1476 return ERROR_NT(status);
1479 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1481 unix_convert(fname,conn,0,&bad_path,&sbuf);
1483 END_PROFILE(SMBopenX);
1484 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1487 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1490 &create_disposition,
1492 END_PROFILE(SMBopenX);
1493 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1496 fsp = open_file_ntcreate(conn,fname,&sbuf,
1506 END_PROFILE(SMBopenX);
1507 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1508 /* We have re-scheduled this call. */
1511 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1514 size = sbuf.st_size;
1516 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1517 if the file is truncated or created. */
1518 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1519 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1520 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1521 close_file(fsp,ERROR_CLOSE);
1522 END_PROFILE(SMBopenX);
1523 return ERROR_NT(NT_STATUS_DISK_FULL);
1525 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1527 close_file(fsp,ERROR_CLOSE);
1528 END_PROFILE(SMBopenX);
1529 return ERROR_NT(NT_STATUS_DISK_FULL);
1531 size = get_allocation_size(conn,fsp,&sbuf);
1534 fattr = dos_mode(conn,fname,&sbuf);
1535 mtime = sbuf.st_mtime;
1537 close_file(fsp,ERROR_CLOSE);
1538 END_PROFILE(SMBopenX);
1539 return ERROR_DOS(ERRDOS,ERRnoaccess);
1542 /* If the caller set the extended oplock request bit
1543 and we granted one (by whatever means) - set the
1544 correct bit for extended oplock reply.
1547 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1548 smb_action |= EXTENDED_OPLOCK_GRANTED;
1551 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1552 smb_action |= EXTENDED_OPLOCK_GRANTED;
1555 /* If the caller set the core oplock request bit
1556 and we granted one (by whatever means) - set the
1557 correct bit for core oplock reply.
1560 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1561 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1564 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1565 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1568 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1569 set_message(outbuf,19,0,True);
1571 set_message(outbuf,15,0,True);
1573 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1574 SSVAL(outbuf,smb_vwv3,fattr);
1575 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1576 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1578 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1580 SIVAL(outbuf,smb_vwv6,(uint32)size);
1581 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1582 SSVAL(outbuf,smb_vwv11,smb_action);
1584 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1585 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1588 END_PROFILE(SMBopenX);
1589 return chain_reply(inbuf,outbuf,length,bufsize);
1592 /****************************************************************************
1593 Reply to a SMBulogoffX.
1594 ****************************************************************************/
1596 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1598 uint16 vuid = SVAL(inbuf,smb_uid);
1599 user_struct *vuser = get_valid_user_struct(vuid);
1600 START_PROFILE(SMBulogoffX);
1603 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1605 /* in user level security we are supposed to close any files
1606 open by this user */
1607 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1608 file_close_user(vuid);
1610 invalidate_vuid(vuid);
1612 set_message(outbuf,2,0,True);
1614 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1616 END_PROFILE(SMBulogoffX);
1617 return chain_reply(inbuf,outbuf,length,bufsize);
1620 /****************************************************************************
1621 Reply to a mknew or a create.
1622 ****************************************************************************/
1624 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1629 uint32 fattr = SVAL(inbuf,smb_vwv0);
1630 BOOL bad_path = False;
1632 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1633 SMB_STRUCT_STAT sbuf;
1635 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1636 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1637 uint32 create_disposition;
1638 uint32 create_options = 0;
1640 START_PROFILE(SMBcreate);
1642 com = SVAL(inbuf,smb_com);
1644 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1645 if (!NT_STATUS_IS_OK(status)) {
1646 END_PROFILE(SMBcreate);
1647 return ERROR_NT(status);
1650 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1652 unix_convert(fname,conn,0,&bad_path,&sbuf);
1654 END_PROFILE(SMBcreate);
1655 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1658 if (fattr & aVOLID) {
1659 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1662 if(com == SMBmknew) {
1663 /* We should fail if file exists. */
1664 create_disposition = FILE_CREATE;
1666 /* Create if file doesn't exist, truncate if it does. */
1667 create_disposition = FILE_OVERWRITE_IF;
1670 /* Open file using ntcreate. */
1671 fsp = open_file_ntcreate(conn,fname,&sbuf,
1681 END_PROFILE(SMBcreate);
1682 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1683 /* We have re-scheduled this call. */
1686 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1689 outsize = set_message(outbuf,1,0,True);
1690 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1692 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1693 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1696 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1697 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1700 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1701 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1703 END_PROFILE(SMBcreate);
1707 /****************************************************************************
1708 Reply to a create temporary file.
1709 ****************************************************************************/
1711 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1715 uint32 fattr = SVAL(inbuf,smb_vwv0);
1716 BOOL bad_path = False;
1718 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1720 SMB_STRUCT_STAT sbuf;
1723 unsigned int namelen;
1725 START_PROFILE(SMBctemp);
1727 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1728 if (!NT_STATUS_IS_OK(status)) {
1729 END_PROFILE(SMBctemp);
1730 return ERROR_NT(status);
1733 pstrcat(fname,"/TMXXXXXX");
1735 pstrcat(fname,"TMXXXXXX");
1738 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1740 unix_convert(fname,conn,0,&bad_path,&sbuf);
1742 END_PROFILE(SMBctemp);
1743 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1746 tmpfd = smb_mkstemp(fname);
1748 END_PROFILE(SMBctemp);
1749 return(UNIXERROR(ERRDOS,ERRnoaccess));
1752 SMB_VFS_STAT(conn,fname,&sbuf);
1754 /* We should fail if file does not exist. */
1755 fsp = open_file_ntcreate(conn,fname,&sbuf,
1756 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1757 FILE_SHARE_READ|FILE_SHARE_WRITE,
1764 /* close fd from smb_mkstemp() */
1768 END_PROFILE(SMBctemp);
1769 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1770 /* We have re-scheduled this call. */
1773 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1776 outsize = set_message(outbuf,1,0,True);
1777 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1779 /* the returned filename is relative to the directory */
1780 s = strrchr_m(fname, '/');
1787 p = smb_buf(outbuf);
1789 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1790 thing in the byte section. JRA */
1791 SSVALS(p, 0, -1); /* what is this? not in spec */
1793 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1795 outsize = set_message_end(outbuf, p);
1797 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1798 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1801 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1802 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1805 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1806 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1807 (unsigned int)sbuf.st_mode ) );
1809 END_PROFILE(SMBctemp);
1813 /*******************************************************************
1814 Check if a user is allowed to rename a file.
1815 ********************************************************************/
1817 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1822 if (!CAN_WRITE(conn)) {
1823 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1826 fmode = dos_mode(conn,fname,pst);
1827 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1828 return NT_STATUS_NO_SUCH_FILE;
1831 if (S_ISDIR(pst->st_mode)) {
1832 return NT_STATUS_OK;
1835 /* We need a better way to return NT status codes from open... */
1836 set_saved_ntstatus(NT_STATUS_OK);
1838 fsp = open_file_ntcreate(conn, fname, pst,
1840 FILE_SHARE_READ|FILE_SHARE_WRITE,
1843 FILE_ATTRIBUTE_NORMAL,
1848 NTSTATUS ret = get_saved_ntstatus();
1849 if (!NT_STATUS_IS_OK(ret)) {
1850 set_saved_ntstatus(NT_STATUS_OK);
1853 set_saved_ntstatus(NT_STATUS_OK);
1854 return NT_STATUS_ACCESS_DENIED;
1856 close_file(fsp,NORMAL_CLOSE);
1857 return NT_STATUS_OK;
1860 /*******************************************************************
1861 Check if a user is allowed to delete a file.
1862 ********************************************************************/
1864 NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
1866 SMB_STRUCT_STAT sbuf;
1870 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1872 if (!CAN_WRITE(conn)) {
1873 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1876 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1877 if(errno == ENOENT) {
1879 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1881 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1884 return map_nt_error_from_unix(errno);
1887 fattr = dos_mode(conn,fname,&sbuf);
1889 /* Can't delete a directory. */
1891 return NT_STATUS_FILE_IS_A_DIRECTORY;
1895 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1896 return NT_STATUS_OBJECT_NAME_INVALID;
1897 #endif /* JRATEST */
1899 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1901 On a Windows share, a file with read-only dosmode can be opened with
1902 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1903 fails with NT_STATUS_CANNOT_DELETE error.
1905 This semantic causes a problem that a user can not
1906 rename a file with read-only dosmode on a Samba share
1907 from a Windows command prompt (i.e. cmd.exe, but can rename
1908 from Windows Explorer).
1911 if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
1912 if (fattr & aRONLY) {
1913 return NT_STATUS_CANNOT_DELETE;
1916 if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1917 return NT_STATUS_NO_SUCH_FILE;
1920 if (check_is_at_open) {
1921 if (!can_delete_file_in_directory(conn, fname)) {
1922 return NT_STATUS_ACCESS_DENIED;
1925 /* On open checks the open itself will check the share mode, so
1926 don't do it here as we'll get it wrong. */
1928 /* We need a better way to return NT status codes from open... */
1929 set_saved_ntstatus(NT_STATUS_OK);
1931 fsp = open_file_ntcreate(conn, fname, &sbuf,
1936 FILE_ATTRIBUTE_NORMAL,
1941 NTSTATUS ret = get_saved_ntstatus();
1942 if (!NT_STATUS_IS_OK(ret)) {
1943 set_saved_ntstatus(NT_STATUS_OK);
1946 set_saved_ntstatus(NT_STATUS_OK);
1947 return NT_STATUS_ACCESS_DENIED;
1949 close_file(fsp,NORMAL_CLOSE);
1951 return NT_STATUS_OK;
1954 /****************************************************************************
1955 The guts of the unlink command, split out so it may be called by the NT SMB
1957 ****************************************************************************/
1959 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
1965 NTSTATUS error = NT_STATUS_OK;
1966 BOOL bad_path = False;
1968 SMB_STRUCT_STAT sbuf;
1970 *directory = *mask = 0;
1972 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1974 p = strrchr_m(name,'/');
1976 pstrcpy(directory,".");
1980 pstrcpy(directory,name);
1985 * We should only check the mangled cache
1986 * here if unix_convert failed. This means
1987 * that the path in 'mask' doesn't exist
1988 * on the file system and so we need to look
1989 * for a possible mangle. This patch from
1990 * Tine Smukavec <valentin.smukavec@hermes.si>.
1993 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
1994 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
1997 pstrcat(directory,"/");
1998 pstrcat(directory,mask);
1999 error = can_delete(conn,directory,dirtype,bad_path,False);
2000 if (!NT_STATUS_IS_OK(error))
2003 if (SMB_VFS_UNLINK(conn,directory) == 0) {
2007 struct smb_Dir *dir_hnd = NULL;
2010 if (strequal(mask,"????????.???"))
2013 if (check_name(directory,conn))
2014 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2016 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2017 the pattern matches against the long name, otherwise the short name
2018 We don't implement this yet XXXX
2023 error = NT_STATUS_NO_SUCH_FILE;
2025 while ((dname = ReadDirName(dir_hnd, &offset))) {
2028 BOOL sys_direntry = False;
2029 pstrcpy(fname,dname);
2031 if (!is_visible_file(conn, directory, dname, &st, True)) {
2035 /* Quick check for "." and ".." */
2036 if (fname[0] == '.') {
2037 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2038 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
2039 sys_direntry = True;
2046 if(!mask_match(fname, mask, conn->case_sensitive))
2050 error = NT_STATUS_OBJECT_NAME_INVALID;
2051 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
2056 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2057 error = can_delete(conn,fname,dirtype,bad_path,False);
2058 if (!NT_STATUS_IS_OK(error)) {
2061 if (SMB_VFS_UNLINK(conn,fname) == 0)
2063 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2069 if (count == 0 && NT_STATUS_IS_OK(error)) {
2070 error = map_nt_error_from_unix(errno);
2076 /****************************************************************************
2078 ****************************************************************************/
2080 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2087 BOOL path_contains_wcard = False;
2089 START_PROFILE(SMBunlink);
2091 dirtype = SVAL(inbuf,smb_vwv0);
2093 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 END_PROFILE(SMBunlink);
2096 return ERROR_NT(status);
2099 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
2101 DEBUG(3,("reply_unlink : %s\n",name));
2103 status = unlink_internals(conn, dirtype, name, path_contains_wcard);
2104 if (!NT_STATUS_IS_OK(status)) {
2105 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2106 /* We have re-scheduled this call. */
2109 return ERROR_NT(status);
2113 * Win2k needs a changenotify request response before it will
2114 * update after a rename..
2116 process_pending_change_notify_queue((time_t)0);
2118 outsize = set_message(outbuf,0,0,False);
2120 END_PROFILE(SMBunlink);
2124 /****************************************************************************
2126 ****************************************************************************/
2128 static void fail_readraw(void)
2131 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2133 exit_server(errstr);
2136 #if defined(WITH_SENDFILE)
2137 /****************************************************************************
2138 Fake (read/write) sendfile. Returns -1 on read or write fail.
2139 ****************************************************************************/
2141 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2145 /* Paranioa check... */
2146 if (nread > bufsize) {
2151 ret = read_file(fsp,buf,startpos,nread);
2157 /* If we had a short read, fill with zeros. */
2159 memset(buf, '\0', nread - ret);
2162 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2166 return (ssize_t)nread;
2170 /****************************************************************************
2171 Use sendfile in readbraw.
2172 ****************************************************************************/
2174 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2175 ssize_t mincount, char *outbuf, int out_buffsize)
2179 #if defined(WITH_SENDFILE)
2181 * We can only use sendfile on a non-chained packet
2182 * but we can use on a non-oplocked file. tridge proved this
2183 * on a train in Germany :-). JRA.
2184 * reply_readbraw has already checked the length.
2187 if ( (chain_size == 0) && (nread > 0) &&
2188 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2191 _smb_setlen(outbuf,nread);
2192 header.data = (uint8 *)outbuf;
2196 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2197 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2198 if (errno == ENOSYS) {
2199 goto normal_readbraw;
2203 * Special hack for broken Linux with no working sendfile. If we
2204 * return EINTR we sent the header but not the rest of the data.
2205 * Fake this up by doing read/write calls.
2207 if (errno == EINTR) {
2208 /* Ensure we don't do this again. */
2209 set_use_sendfile(SNUM(conn), False);
2210 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2212 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2213 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2214 fsp->fsp_name, strerror(errno) ));
2215 exit_server("send_file_readbraw fake_sendfile failed");
2220 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2221 fsp->fsp_name, strerror(errno) ));
2222 exit_server("send_file_readbraw sendfile failed");
2232 ret = read_file(fsp,outbuf+4,startpos,nread);
2233 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2242 _smb_setlen(outbuf,ret);
2243 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2247 /****************************************************************************
2248 Reply to a readbraw (core+ protocol).
2249 ****************************************************************************/
2251 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2253 ssize_t maxcount,mincount;
2256 char *header = outbuf;
2258 START_PROFILE(SMBreadbraw);
2260 if (srv_is_signing_active()) {
2261 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2265 * Special check if an oplock break has been issued
2266 * and the readraw request croses on the wire, we must
2267 * return a zero length response here.
2270 fsp = file_fsp(inbuf,smb_vwv0);
2272 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2274 * fsp could be NULL here so use the value from the packet. JRA.
2276 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2277 _smb_setlen(header,0);
2278 if (write_data(smbd_server_fd(),header,4) != 4)
2280 END_PROFILE(SMBreadbraw);
2284 CHECK_FSP(fsp,conn);
2286 flush_write_cache(fsp, READRAW_FLUSH);
2288 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2289 if(CVAL(inbuf,smb_wct) == 10) {
2291 * This is a large offset (64 bit) read.
2293 #ifdef LARGE_SMB_OFF_T
2295 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2297 #else /* !LARGE_SMB_OFF_T */
2300 * Ensure we haven't been sent a >32 bit offset.
2303 if(IVAL(inbuf,smb_vwv8) != 0) {
2304 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2305 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2306 _smb_setlen(header,0);
2307 if (write_data(smbd_server_fd(),header,4) != 4)
2309 END_PROFILE(SMBreadbraw);
2313 #endif /* LARGE_SMB_OFF_T */
2316 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2317 _smb_setlen(header,0);
2318 if (write_data(smbd_server_fd(),header,4) != 4)
2320 END_PROFILE(SMBreadbraw);
2324 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2325 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2327 /* ensure we don't overrun the packet size */
2328 maxcount = MIN(65535,maxcount);
2330 if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2334 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2338 if (startpos >= size) {
2341 nread = MIN(maxcount,(size - startpos));
2345 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2346 if (nread < mincount)
2350 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2351 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2353 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2355 DEBUG(5,("readbraw finished\n"));
2356 END_PROFILE(SMBreadbraw);
2361 #define DBGC_CLASS DBGC_LOCKING
2363 /****************************************************************************
2364 Reply to a lockread (core+ protocol).
2365 ****************************************************************************/
2367 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2375 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2376 BOOL my_lock_ctx = False;
2377 START_PROFILE(SMBlockread);
2379 CHECK_FSP(fsp,conn);
2380 if (!CHECK_READ(fsp,inbuf)) {
2381 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2384 release_level_2_oplocks_on_change(fsp);
2386 numtoread = SVAL(inbuf,smb_vwv1);
2387 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2389 outsize = set_message(outbuf,5,3,True);
2390 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2391 data = smb_buf(outbuf) + 3;
2394 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2395 * protocol request that predates the read/write lock concept.
2396 * Thus instead of asking for a read lock here we need to ask
2397 * for a write lock. JRA.
2398 * Note that the requested lock size is unaffected by max_recv.
2401 status = do_lock_spin(fsp,
2402 SVAL(inbuf,smb_pid),
2403 (SMB_BIG_UINT)numtoread,
2404 (SMB_BIG_UINT)startpos,
2409 if (NT_STATUS_V(status)) {
2412 * We used to make lockread a blocking lock. It turns out
2413 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2417 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2419 * A blocking lock was requested. Package up
2420 * this smb into a queued request and push it
2421 * onto the blocking lock queue.
2423 if(push_blocking_lock_request(inbuf, length,
2427 SVAL(inbuf,smb_pid),
2430 (SMB_BIG_UINT)startpos,
2431 (SMB_BIG_UINT)numtoread)) {
2432 END_PROFILE(SMBlockread);
2437 END_PROFILE(SMBlockread);
2438 return ERROR_NT(status);
2442 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2445 if (numtoread > max_recv) {
2446 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2447 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2448 (unsigned int)numtoread, (unsigned int)max_recv ));
2449 numtoread = MIN(numtoread,max_recv);
2451 nread = read_file(fsp,data,startpos,numtoread);
2454 END_PROFILE(SMBlockread);
2455 return(UNIXERROR(ERRDOS,ERRnoaccess));
2459 SSVAL(outbuf,smb_vwv0,nread);
2460 SSVAL(outbuf,smb_vwv5,nread+3);
2461 SSVAL(smb_buf(outbuf),1,nread);
2463 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2464 fsp->fnum, (int)numtoread, (int)nread));
2466 END_PROFILE(SMBlockread);
2471 #define DBGC_CLASS DBGC_ALL
2473 /****************************************************************************
2475 ****************************************************************************/
2477 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2484 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2485 START_PROFILE(SMBread);
2487 CHECK_FSP(fsp,conn);
2488 if (!CHECK_READ(fsp,inbuf)) {
2489 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2492 numtoread = SVAL(inbuf,smb_vwv1);
2493 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2495 outsize = set_message(outbuf,5,3,True);
2496 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2498 * The requested read size cannot be greater than max_recv. JRA.
2500 if (numtoread > max_recv) {
2501 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2502 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2503 (unsigned int)numtoread, (unsigned int)max_recv ));
2504 numtoread = MIN(numtoread,max_recv);
2507 data = smb_buf(outbuf) + 3;
2509 if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2510 END_PROFILE(SMBread);
2511 return ERROR_DOS(ERRDOS,ERRlock);
2515 nread = read_file(fsp,data,startpos,numtoread);
2518 END_PROFILE(SMBread);
2519 return(UNIXERROR(ERRDOS,ERRnoaccess));
2523 SSVAL(outbuf,smb_vwv0,nread);
2524 SSVAL(outbuf,smb_vwv5,nread+3);
2525 SCVAL(smb_buf(outbuf),0,1);
2526 SSVAL(smb_buf(outbuf),1,nread);
2528 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2529 fsp->fnum, (int)numtoread, (int)nread ) );
2531 END_PROFILE(SMBread);
2535 /****************************************************************************
2536 Reply to a read and X - possibly using sendfile.
2537 ****************************************************************************/
2539 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2540 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2544 char *data = smb_buf(outbuf);
2546 #if defined(WITH_SENDFILE)
2548 * We can only use sendfile on a non-chained packet
2549 * but we can use on a non-oplocked file. tridge proved this
2550 * on a train in Germany :-). JRA.
2553 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2554 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2555 SMB_STRUCT_STAT sbuf;
2558 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2559 return(UNIXERROR(ERRDOS,ERRnoaccess));
2561 if (startpos > sbuf.st_size)
2564 if (smb_maxcnt > (sbuf.st_size - startpos))
2565 smb_maxcnt = (sbuf.st_size - startpos);
2567 if (smb_maxcnt == 0)
2571 * Set up the packet header before send. We
2572 * assume here the sendfile will work (get the
2573 * correct amount of data).
2576 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2577 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2578 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2579 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2580 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2581 SCVAL(outbuf,smb_vwv0,0xFF);
2582 set_message(outbuf,12,smb_maxcnt,False);
2583 header.data = (uint8 *)outbuf;
2584 header.length = data - outbuf;
2587 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2588 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2589 if (errno == ENOSYS) {
2594 * Special hack for broken Linux with no working sendfile. If we
2595 * return EINTR we sent the header but not the rest of the data.
2596 * Fake this up by doing read/write calls.
2599 if (errno == EINTR) {
2600 /* Ensure we don't do this again. */
2601 set_use_sendfile(SNUM(conn), False);
2602 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2604 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2605 len_outbuf - (data-outbuf))) == -1) {
2606 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2607 fsp->fsp_name, strerror(errno) ));
2608 exit_server("send_file_readX: fake_sendfile failed");
2610 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2611 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2612 /* Returning -1 here means successful sendfile. */
2616 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2617 fsp->fsp_name, strerror(errno) ));
2618 exit_server("send_file_readX sendfile failed");
2621 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2622 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2623 /* Returning -1 here means successful sendfile. */
2631 nread = read_file(fsp,data,startpos,smb_maxcnt);
2634 return(UNIXERROR(ERRDOS,ERRnoaccess));
2637 outsize = set_message(outbuf,12,nread,False);
2638 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2639 SSVAL(outbuf,smb_vwv5,nread);
2640 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2641 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2642 SSVAL(smb_buf(outbuf),-2,nread);
2644 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2645 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2647 /* Returning the number of bytes we want to send back - including header. */
2651 /****************************************************************************
2652 Reply to a read and X.
2653 ****************************************************************************/
2655 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2657 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2658 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2660 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2662 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2665 START_PROFILE(SMBreadX);
2667 /* If it's an IPC, pass off the pipe handler. */
2669 END_PROFILE(SMBreadX);
2670 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2673 CHECK_FSP(fsp,conn);
2674 if (!CHECK_READ(fsp,inbuf)) {
2675 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2678 set_message(outbuf,12,0,True);
2680 if (global_client_caps & CAP_LARGE_READX) {
2681 if (SVAL(inbuf,smb_vwv7) == 1) {
2682 smb_maxcnt |= (1<<16);
2684 if (smb_maxcnt > BUFFER_SIZE) {
2685 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2686 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2687 END_PROFILE(SMBreadX);
2688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2692 if(CVAL(inbuf,smb_wct) == 12) {
2693 #ifdef LARGE_SMB_OFF_T
2695 * This is a large offset (64 bit) read.
2697 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2699 #else /* !LARGE_SMB_OFF_T */
2702 * Ensure we haven't been sent a >32 bit offset.
2705 if(IVAL(inbuf,smb_vwv10) != 0) {
2706 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2707 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2708 END_PROFILE(SMBreadX);
2709 return ERROR_DOS(ERRDOS,ERRbadaccess);
2712 #endif /* LARGE_SMB_OFF_T */
2716 if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2717 END_PROFILE(SMBreadX);
2718 return ERROR_DOS(ERRDOS,ERRlock);
2721 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2722 END_PROFILE(SMBreadX);
2726 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2728 nread = chain_reply(inbuf,outbuf,length,bufsize);
2730 END_PROFILE(SMBreadX);
2734 /****************************************************************************
2735 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2736 ****************************************************************************/
2738 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2741 ssize_t total_written=0;
2742 size_t numtowrite=0;
2747 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2749 START_PROFILE(SMBwritebraw);
2751 if (srv_is_signing_active()) {
2752 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2755 CHECK_FSP(fsp,conn);
2756 if (!CHECK_WRITE(fsp)) {
2757 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2760 tcount = IVAL(inbuf,smb_vwv1);
2761 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2762 write_through = BITSETW(inbuf+smb_vwv7,0);
2764 /* We have to deal with slightly different formats depending
2765 on whether we are using the core+ or lanman1.0 protocol */
2767 if(Protocol <= PROTOCOL_COREPLUS) {
2768 numtowrite = SVAL(smb_buf(inbuf),-2);
2769 data = smb_buf(inbuf);
2771 numtowrite = SVAL(inbuf,smb_vwv10);
2772 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2775 /* force the error type */
2776 SCVAL(inbuf,smb_com,SMBwritec);
2777 SCVAL(outbuf,smb_com,SMBwritec);
2779 if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2780 END_PROFILE(SMBwritebraw);
2781 return(ERROR_DOS(ERRDOS,ERRlock));
2785 nwritten = write_file(fsp,data,startpos,numtowrite);
2787 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2788 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2790 if (nwritten < (ssize_t)numtowrite) {
2791 END_PROFILE(SMBwritebraw);
2792 return(UNIXERROR(ERRHRD,ERRdiskfull));
2795 total_written = nwritten;
2797 /* Return a message to the redirector to tell it to send more bytes */
2798 SCVAL(outbuf,smb_com,SMBwritebraw);
2799 SSVALS(outbuf,smb_vwv0,-1);
2800 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2802 if (!send_smb(smbd_server_fd(),outbuf))
2803 exit_server("reply_writebraw: send_smb failed.");
2805 /* Now read the raw data into the buffer and write it */
2806 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2807 exit_server("secondary writebraw failed");
2810 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2811 numtowrite = smb_len(inbuf);
2813 /* Set up outbuf to return the correct return */
2814 outsize = set_message(outbuf,1,0,True);
2815 SCVAL(outbuf,smb_com,SMBwritec);
2817 if (numtowrite != 0) {
2819 if (numtowrite > BUFFER_SIZE) {
2820 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2821 (unsigned int)numtowrite ));
2822 exit_server("secondary writebraw failed");
2825 if (tcount > nwritten+numtowrite) {
2826 DEBUG(3,("Client overestimated the write %d %d %d\n",
2827 (int)tcount,(int)nwritten,(int)numtowrite));
2830 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2831 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2833 exit_server("secondary writebraw failed");
2836 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2838 if (nwritten < (ssize_t)numtowrite) {
2839 SCVAL(outbuf,smb_rcls,ERRHRD);
2840 SSVAL(outbuf,smb_err,ERRdiskfull);
2844 total_written += nwritten;
2847 SSVAL(outbuf,smb_vwv0,total_written);
2849 sync_file(conn, fsp, write_through);
2851 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2852 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2854 /* we won't return a status if write through is not selected - this follows what WfWg does */
2855 END_PROFILE(SMBwritebraw);
2856 if (!write_through && total_written==tcount) {
2858 #if RABBIT_PELLET_FIX
2860 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2861 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2863 if (!send_keepalive(smbd_server_fd()))
2864 exit_server("reply_writebraw: send of keepalive failed");
2873 #define DBGC_CLASS DBGC_LOCKING
2875 /****************************************************************************
2876 Reply to a writeunlock (core+).
2877 ****************************************************************************/
2879 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2880 int size, int dum_buffsize)
2882 ssize_t nwritten = -1;
2886 NTSTATUS status = NT_STATUS_OK;
2887 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2889 START_PROFILE(SMBwriteunlock);
2891 CHECK_FSP(fsp,conn);
2892 if (!CHECK_WRITE(fsp)) {
2893 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2896 numtowrite = SVAL(inbuf,smb_vwv1);
2897 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2898 data = smb_buf(inbuf) + 3;
2900 if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2901 END_PROFILE(SMBwriteunlock);
2902 return ERROR_DOS(ERRDOS,ERRlock);
2905 /* The special X/Open SMB protocol handling of
2906 zero length writes is *NOT* done for
2908 if(numtowrite == 0) {
2911 nwritten = write_file(fsp,data,startpos,numtowrite);
2914 sync_file(conn, fsp, False /* write through */);
2916 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2917 END_PROFILE(SMBwriteunlock);
2918 return(UNIXERROR(ERRHRD,ERRdiskfull));
2922 status = do_unlock(fsp,
2923 SVAL(inbuf,smb_pid),
2924 (SMB_BIG_UINT)numtowrite,
2925 (SMB_BIG_UINT)startpos,
2928 if (NT_STATUS_V(status)) {
2929 END_PROFILE(SMBwriteunlock);
2930 return ERROR_NT(status);
2934 outsize = set_message(outbuf,1,0,True);
2936 SSVAL(outbuf,smb_vwv0,nwritten);
2938 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2939 fsp->fnum, (int)numtowrite, (int)nwritten));
2941 END_PROFILE(SMBwriteunlock);
2946 #define DBGC_CLASS DBGC_ALL
2948 /****************************************************************************
2950 ****************************************************************************/
2952 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2955 ssize_t nwritten = -1;
2958 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2960 START_PROFILE(SMBwrite);
2962 /* If it's an IPC, pass off the pipe handler. */
2964 END_PROFILE(SMBwrite);
2965 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2968 CHECK_FSP(fsp,conn);
2969 if (!CHECK_WRITE(fsp)) {
2970 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2973 numtowrite = SVAL(inbuf,smb_vwv1);
2974 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2975 data = smb_buf(inbuf) + 3;
2977 if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2978 END_PROFILE(SMBwrite);
2979 return ERROR_DOS(ERRDOS,ERRlock);
2983 * X/Open SMB protocol says that if smb_vwv1 is
2984 * zero then the file size should be extended or
2985 * truncated to the size given in smb_vwv[2-3].
2988 if(numtowrite == 0) {
2990 * This is actually an allocate call, and set EOF. JRA.
2992 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2994 END_PROFILE(SMBwrite);
2995 return ERROR_NT(NT_STATUS_DISK_FULL);
2997 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2999 END_PROFILE(SMBwrite);
3000 return ERROR_NT(NT_STATUS_DISK_FULL);
3003 nwritten = write_file(fsp,data,startpos,numtowrite);
3005 sync_file(conn, fsp, False);
3007 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3008 END_PROFILE(SMBwrite);
3009 return(UNIXERROR(ERRHRD,ERRdiskfull));
3012 outsize = set_message(outbuf,1,0,True);
3014 SSVAL(outbuf,smb_vwv0,nwritten);
3016 if (nwritten < (ssize_t)numtowrite) {
3017 SCVAL(outbuf,smb_rcls,ERRHRD);
3018 SSVAL(outbuf,smb_err,ERRdiskfull);
3021 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3023 END_PROFILE(SMBwrite);
3027 /****************************************************************************
3028 Reply to a write and X.
3029 ****************************************************************************/
3031 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3033 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3034 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3035 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3036 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3037 ssize_t nwritten = -1;
3038 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3039 unsigned int smblen = smb_len(inbuf);
3041 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3042 START_PROFILE(SMBwriteX);
3044 /* If it's an IPC, pass off the pipe handler. */
3046 END_PROFILE(SMBwriteX);
3047 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3050 CHECK_FSP(fsp,conn);
3051 if (!CHECK_WRITE(fsp)) {
3052 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3055 set_message(outbuf,6,0,True);
3057 /* Deal with possible LARGE_WRITEX */
3059 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3062 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3063 END_PROFILE(SMBwriteX);
3064 return ERROR_DOS(ERRDOS,ERRbadmem);
3067 data = smb_base(inbuf) + smb_doff;
3069 if(CVAL(inbuf,smb_wct) == 14) {
3070 #ifdef LARGE_SMB_OFF_T
3072 * This is a large offset (64 bit) write.
3074 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3076 #else /* !LARGE_SMB_OFF_T */
3079 * Ensure we haven't been sent a >32 bit offset.
3082 if(IVAL(inbuf,smb_vwv12) != 0) {
3083 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3084 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3085 END_PROFILE(SMBwriteX);
3086 return ERROR_DOS(ERRDOS,ERRbadaccess);
3089 #endif /* LARGE_SMB_OFF_T */
3092 if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3093 END_PROFILE(SMBwriteX);
3094 return ERROR_DOS(ERRDOS,ERRlock);
3097 /* X/Open SMB protocol says that, unlike SMBwrite
3098 if the length is zero then NO truncation is
3099 done, just a write of zero. To truncate a file,
3102 if(numtowrite == 0) {
3106 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3107 fsp,data,startpos,numtowrite)) {
3108 END_PROFILE(SMBwriteX);
3112 nwritten = write_file(fsp,data,startpos,numtowrite);
3115 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3116 END_PROFILE(SMBwriteX);
3117 return(UNIXERROR(ERRHRD,ERRdiskfull));
3120 SSVAL(outbuf,smb_vwv2,nwritten);
3122 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3124 if (nwritten < (ssize_t)numtowrite) {
3125 SCVAL(outbuf,smb_rcls,ERRHRD);
3126 SSVAL(outbuf,smb_err,ERRdiskfull);
3129 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3130 fsp->fnum, (int)numtowrite, (int)nwritten));
3132 sync_file(conn, fsp, write_through);
3134 END_PROFILE(SMBwriteX);
3135 return chain_reply(inbuf,outbuf,length,bufsize);
3138 /****************************************************************************
3140 ****************************************************************************/
3142 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3148 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3149 START_PROFILE(SMBlseek);
3151 CHECK_FSP(fsp,conn);
3153 flush_write_cache(fsp, SEEK_FLUSH);
3155 mode = SVAL(inbuf,smb_vwv1) & 3;
3156 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3157 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3166 res = fsp->fh->pos + startpos;
3177 if (umode == SEEK_END) {
3178 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3179 if(errno == EINVAL) {
3180 SMB_OFF_T current_pos = startpos;
3181 SMB_STRUCT_STAT sbuf;
3183 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3184 END_PROFILE(SMBlseek);
3185 return(UNIXERROR(ERRDOS,ERRnoaccess));
3188 current_pos += sbuf.st_size;
3190 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3195 END_PROFILE(SMBlseek);
3196 return(UNIXERROR(ERRDOS,ERRnoaccess));
3202 outsize = set_message(outbuf,2,0,True);
3203 SIVAL(outbuf,smb_vwv0,res);
3205 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3206 fsp->fnum, (double)startpos, (double)res, mode));
3208 END_PROFILE(SMBlseek);
3212 /****************************************************************************
3214 ****************************************************************************/
3216 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3218 int outsize = set_message(outbuf,0,0,False);
3219 uint16 fnum = SVAL(inbuf,smb_vwv0);
3220 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3221 START_PROFILE(SMBflush);
3224 CHECK_FSP(fsp,conn);
3227 file_sync_all(conn);
3229 sync_file(conn,fsp, True);
3232 DEBUG(3,("flush\n"));
3233 END_PROFILE(SMBflush);
3237 /****************************************************************************
3239 ****************************************************************************/
3241 int reply_exit(connection_struct *conn,
3242 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3245 START_PROFILE(SMBexit);
3247 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3249 outsize = set_message(outbuf,0,0,False);
3251 DEBUG(3,("exit\n"));
3253 END_PROFILE(SMBexit);
3257 /****************************************************************************
3258 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3259 ****************************************************************************/
3261 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3266 int32 eclass = 0, err = 0;
3267 files_struct *fsp = NULL;
3268 START_PROFILE(SMBclose);
3270 outsize = set_message(outbuf,0,0,False);
3272 /* If it's an IPC, pass off to the pipe handler. */
3274 END_PROFILE(SMBclose);
3275 return reply_pipe_close(conn, inbuf,outbuf);
3278 fsp = file_fsp(inbuf,smb_vwv0);
3281 * We can only use CHECK_FSP if we know it's not a directory.
3284 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3285 END_PROFILE(SMBclose);
3286 return ERROR_DOS(ERRDOS,ERRbadfid);
3289 if(fsp->is_directory) {
3291 * Special case - close NT SMB directory handle.
3293 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3294 close_file(fsp,NORMAL_CLOSE);
3297 * Close ordinary file.
3302 /* Save the name for time set in close. */
3303 pstrcpy( file_name, fsp->fsp_name);
3305 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3306 fsp->fh->fd, fsp->fnum,
3307 conn->num_files_open));
3310 * Take care of any time sent in the close.
3313 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3314 fsp_set_pending_modtime(fsp, mtime);
3317 * close_file() returns the unix errno if an error
3318 * was detected on close - normally this is due to
3319 * a disk full error. If not then it was probably an I/O error.
3322 if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
3324 END_PROFILE(SMBclose);
3325 return (UNIXERROR(ERRHRD,ERRgeneral));
3329 /* We have a cached error */
3331 END_PROFILE(SMBclose);
3332 return ERROR_DOS(eclass,err);
3335 END_PROFILE(SMBclose);
3339 /****************************************************************************
3340 Reply to a writeclose (Core+ protocol).
3341 ****************************************************************************/
3343 int reply_writeclose(connection_struct *conn,
3344 char *inbuf,char *outbuf, int size, int dum_buffsize)
3347 ssize_t nwritten = -1;
3353 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3354 START_PROFILE(SMBwriteclose);
3356 CHECK_FSP(fsp,conn);
3357 if (!CHECK_WRITE(fsp)) {
3358 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3361 numtowrite = SVAL(inbuf,smb_vwv1);
3362 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3363 mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3364 data = smb_buf(inbuf) + 1;
3366 if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3367 END_PROFILE(SMBwriteclose);
3368 return ERROR_DOS(ERRDOS,ERRlock);
3371 nwritten = write_file(fsp,data,startpos,numtowrite);
3373 set_filetime(conn, fsp->fsp_name,mtime);
3376 * More insanity. W2K only closes the file if writelen > 0.
3381 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3383 close_err = close_file(fsp,NORMAL_CLOSE);
3386 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3387 fsp->fnum, (int)numtowrite, (int)nwritten,
3388 conn->num_files_open));
3390 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3391 END_PROFILE(SMBwriteclose);
3392 return(UNIXERROR(ERRHRD,ERRdiskfull));
3395 if(close_err != 0) {
3397 END_PROFILE(SMBwriteclose);
3398 return(UNIXERROR(ERRHRD,ERRgeneral));
3401 outsize = set_message(outbuf,1,0,True);
3403 SSVAL(outbuf,smb_vwv0,nwritten);
3404 END_PROFILE(SMBwriteclose);
3409 #define DBGC_CLASS DBGC_LOCKING
3411 /****************************************************************************
3413 ****************************************************************************/
3415 int reply_lock(connection_struct *conn,
3416 char *inbuf,char *outbuf, int length, int dum_buffsize)
3418 int outsize = set_message(outbuf,0,0,False);
3419 SMB_BIG_UINT count,offset;
3421 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3422 BOOL my_lock_ctx = False;
3424 START_PROFILE(SMBlock);
3426 CHECK_FSP(fsp,conn);
3428 release_level_2_oplocks_on_change(fsp);
3430 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3431 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3433 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3434 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3436 status = do_lock_spin(fsp,
3437 SVAL(inbuf,smb_pid),
3443 if (NT_STATUS_V(status)) {
3445 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3446 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3448 * A blocking lock was requested. Package up
3449 * this smb into a queued request and push it
3450 * onto the blocking lock queue.
3452 if(push_blocking_lock_request(inbuf, length,
3456 SVAL(inbuf,smb_pid),
3460 END_PROFILE(SMBlock);
3465 END_PROFILE(SMBlock);
3466 return ERROR_NT(status);
3469 END_PROFILE(SMBlock);
3473 /****************************************************************************
3475 ****************************************************************************/
3477 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3480 int outsize = set_message(outbuf,0,0,False);
3481 SMB_BIG_UINT count,offset;
3483 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3484 START_PROFILE(SMBunlock);
3486 CHECK_FSP(fsp,conn);
3488 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3489 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3491 status = do_unlock(fsp,
3492 SVAL(inbuf,smb_pid),
3497 if (NT_STATUS_V(status)) {
3498 END_PROFILE(SMBunlock);
3499 return ERROR_NT(status);
3502 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3503 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3505 END_PROFILE(SMBunlock);
3510 #define DBGC_CLASS DBGC_ALL
3512 /****************************************************************************
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 ****************************************************************************/
3543 int reply_echo(connection_struct *conn,
3544 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3546 int smb_reverb = SVAL(inbuf,smb_vwv0);
3548 unsigned int data_len = smb_buflen(inbuf);
3549 int outsize = set_message(outbuf,1,data_len,True);
3550 START_PROFILE(SMBecho);
3552 if (data_len > BUFFER_SIZE) {
3553 DEBUG(0,("reply_echo: data_len too large.\n"));
3554 END_PROFILE(SMBecho);
3558 /* copy any incoming data back out */
3560 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3562 if (smb_reverb > 100) {
3563 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3567 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3568 SSVAL(outbuf,smb_vwv0,seq_num);
3570 smb_setlen(outbuf,outsize - 4);
3573 if (!send_smb(smbd_server_fd(),outbuf))
3574 exit_server("reply_echo: send_smb failed.");
3577 DEBUG(3,("echo %d times\n", smb_reverb));
3581 END_PROFILE(SMBecho);
3585 /****************************************************************************
3586 Reply to a printopen.
3587 ****************************************************************************/
3589 int reply_printopen(connection_struct *conn,
3590 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3594 START_PROFILE(SMBsplopen);
3596 if (!CAN_PRINT(conn)) {
3597 END_PROFILE(SMBsplopen);
3598 return ERROR_DOS(ERRDOS,ERRnoaccess);
3601 /* Open for exclusive use, write only. */
3602 fsp = print_fsp_open(conn, NULL);
3605 END_PROFILE(SMBsplopen);
3606 return(UNIXERROR(ERRDOS,ERRnoaccess));
3609 outsize = set_message(outbuf,1,0,True);
3610 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3612 DEBUG(3,("openprint fd=%d fnum=%d\n",
3613 fsp->fh->fd, fsp->fnum));
3615 END_PROFILE(SMBsplopen);
3619 /****************************************************************************
3620 Reply to a printclose.
3621 ****************************************************************************/
3623 int reply_printclose(connection_struct *conn,
3624 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3626 int outsize = set_message(outbuf,0,0,False);
3627 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3629 START_PROFILE(SMBsplclose);
3631 CHECK_FSP(fsp,conn);
3633 if (!CAN_PRINT(conn)) {
3634 END_PROFILE(SMBsplclose);
3635 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3638 DEBUG(3,("printclose fd=%d fnum=%d\n",
3639 fsp->fh->fd,fsp->fnum));
3641 close_err = close_file(fsp,NORMAL_CLOSE);
3643 if(close_err != 0) {
3645 END_PROFILE(SMBsplclose);
3646 return(UNIXERROR(ERRHRD,ERRgeneral));
3649 END_PROFILE(SMBsplclose);
3653 /****************************************************************************
3654 Reply to a printqueue.
3655 ****************************************************************************/
3657 int reply_printqueue(connection_struct *conn,
3658 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3660 int outsize = set_message(outbuf,2,3,True);
3661 int max_count = SVAL(inbuf,smb_vwv0);
3662 int start_index = SVAL(inbuf,smb_vwv1);
3663 START_PROFILE(SMBsplretq);
3665 /* we used to allow the client to get the cnum wrong, but that
3666 is really quite gross and only worked when there was only
3667 one printer - I think we should now only accept it if they
3668 get it right (tridge) */
3669 if (!CAN_PRINT(conn)) {
3670 END_PROFILE(SMBsplretq);
3671 return ERROR_DOS(ERRDOS,ERRnoaccess);
3674 SSVAL(outbuf,smb_vwv0,0);
3675 SSVAL(outbuf,smb_vwv1,0);
3676 SCVAL(smb_buf(outbuf),0,1);
3677 SSVAL(smb_buf(outbuf),1,0);
3679 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3680 start_index, max_count));
3683 print_queue_struct *queue = NULL;
3684 print_status_struct status;
3685 char *p = smb_buf(outbuf) + 3;
3686 int count = print_queue_status(SNUM(conn), &queue, &status);
3687 int num_to_get = ABS(max_count);
3688 int first = (max_count>0?start_index:start_index+max_count+1);
3694 num_to_get = MIN(num_to_get,count-first);
3697 for (i=first;i<first+num_to_get;i++) {
3698 srv_put_dos_date2(p,0,queue[i].time);
3699 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3700 SSVAL(p,5, queue[i].job);
3701 SIVAL(p,7,queue[i].size);
3703 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3708 outsize = set_message(outbuf,2,28*count+3,False);
3709 SSVAL(outbuf,smb_vwv0,count);
3710 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3711 SCVAL(smb_buf(outbuf),0,1);
3712 SSVAL(smb_buf(outbuf),1,28*count);
3717 DEBUG(3,("%d entries returned in queue\n",count));
3720 END_PROFILE(SMBsplretq);
3724 /****************************************************************************
3725 Reply to a printwrite.
3726 ****************************************************************************/
3728 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3731 int outsize = set_message(outbuf,0,0,False);
3733 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3735 START_PROFILE(SMBsplwr);
3737 if (!CAN_PRINT(conn)) {
3738 END_PROFILE(SMBsplwr);
3739 return ERROR_DOS(ERRDOS,ERRnoaccess);
3742 CHECK_FSP(fsp,conn);
3743 if (!CHECK_WRITE(fsp)) {
3744 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3747 numtowrite = SVAL(smb_buf(inbuf),1);
3748 data = smb_buf(inbuf) + 3;
3750 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3751 END_PROFILE(SMBsplwr);
3752 return(UNIXERROR(ERRHRD,ERRdiskfull));
3755 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3757 END_PROFILE(SMBsplwr);
3761 /****************************************************************************
3762 The guts of the mkdir command, split out so it may be called by the NT SMB
3764 ****************************************************************************/
3766 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3770 if(!CAN_WRITE(conn)) {
3771 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3773 return map_nt_error_from_unix(errno);
3777 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3780 if (!check_name(directory, conn)) {
3781 if(errno == ENOENT) {
3783 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3785 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3788 return map_nt_error_from_unix(errno);
3791 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3793 if(errno == ENOENT) {
3794 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3796 return map_nt_error_from_unix(errno);
3799 return NT_STATUS_OK;
3802 /****************************************************************************
3804 ****************************************************************************/
3806 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3811 BOOL bad_path = False;
3812 SMB_STRUCT_STAT sbuf;
3814 START_PROFILE(SMBmkdir);
3816 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3817 if (!NT_STATUS_IS_OK(status)) {
3818 END_PROFILE(SMBmkdir);
3819 return ERROR_NT(status);
3822 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3824 unix_convert(directory,conn,0,&bad_path,&sbuf);
3826 if( is_ntfs_stream_name(directory)) {
3827 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3828 END_PROFILE(SMBmkdir);
3829 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
3832 status = mkdir_internal(conn, directory,bad_path);
3833 if (!NT_STATUS_IS_OK(status)) {
3834 END_PROFILE(SMBmkdir);
3835 return ERROR_NT(status);
3838 if (lp_inherit_owner(SNUM(conn))) {
3839 /* Ensure we're checking for a symlink here.... */
3840 /* We don't want to get caught by a symlink racer. */
3842 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3843 END_PROFILE(SMBmkdir);
3844 return(UNIXERROR(ERRDOS,ERRnoaccess));
3847 if(!S_ISDIR(sbuf.st_mode)) {
3848 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3849 END_PROFILE(SMBmkdir);
3850 return(UNIXERROR(ERRDOS,ERRnoaccess));
3853 change_owner_to_parent(conn, NULL, directory, &sbuf);
3856 outsize = set_message(outbuf,0,0,False);
3858 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3860 END_PROFILE(SMBmkdir);
3864 /****************************************************************************
3865 Static function used by reply_rmdir to delete an entire directory
3866 tree recursively. Return False on ok, True on fail.
3867 ****************************************************************************/
3869 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3871 const char *dname = NULL;
3874 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3879 while((dname = ReadDirName(dir_hnd, &offset))) {
3883 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3886 if (!is_visible_file(conn, directory, dname, &st, False))
3889 /* Construct the full name. */
3890 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3896 pstrcpy(fullname, directory);
3897 pstrcat(fullname, "/");
3898 pstrcat(fullname, dname);
3900 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3905 if(st.st_mode & S_IFDIR) {
3906 if(recursive_rmdir(conn, fullname)!=0) {
3910 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3914 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3923 /****************************************************************************
3924 The internals of the rmdir code - called elsewhere.
3925 ****************************************************************************/
3927 BOOL rmdir_internals(connection_struct *conn, char *directory)
3932 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3933 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3935 * Check to see if the only thing in this directory are
3936 * vetoed files/directories. If so then delete them and
3937 * retry. If we fail to delete any of them (and we *don't*
3938 * do a recursive delete) then fail the rmdir.
3940 BOOL all_veto_files = True;
3942 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3944 if(dir_hnd != NULL) {
3946 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3947 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3949 if (!is_visible_file(conn, directory, dname, &st, False))
3951 if(!IS_VETO_PATH(conn, dname)) {
3952 all_veto_files = False;
3957 if(all_veto_files) {
3958 RewindDir(dir_hnd,&dirpos);
3959 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3962 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3964 if (!is_visible_file(conn, directory, dname, &st, False))
3967 /* Construct the full name. */
3968 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3973 pstrcpy(fullname, directory);
3974 pstrcat(fullname, "/");
3975 pstrcat(fullname, dname);
3977 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3979 if(st.st_mode & S_IFDIR) {
3980 if(lp_recursive_veto_delete(SNUM(conn))) {
3981 if(recursive_rmdir(conn, fullname) != 0)
3984 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3986 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3990 /* Retry the rmdir */
3991 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
4001 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
4006 /****************************************************************************
4008 ****************************************************************************/
4010 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4015 BOOL bad_path = False;
4016 SMB_STRUCT_STAT sbuf;
4018 START_PROFILE(SMBrmdir);
4020 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
4021 if (!NT_STATUS_IS_OK(status)) {
4022 END_PROFILE(SMBrmdir);
4023 return ERROR_NT(status);
4026 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
4028 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
4030 END_PROFILE(SMBrmdir);
4031 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4034 if (check_name(directory,conn)) {
4035 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4036 ok = rmdir_internals(conn, directory);
4040 END_PROFILE(SMBrmdir);
4041 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
4044 outsize = set_message(outbuf,0,0,False);
4046 DEBUG( 3, ( "rmdir %s\n", directory ) );
4048 END_PROFILE(SMBrmdir);
4052 /*******************************************************************
4053 Resolve wildcards in a filename rename.
4054 Note that name is in UNIX charset and thus potentially can be more
4055 than fstring buffer (255 bytes) especially in default UTF-8 case.
4056 Therefore, we use pstring inside and all calls should ensure that
4057 name2 is at least pstring-long (they do already)
4058 ********************************************************************/
4060 static BOOL resolve_wildcards(const char *name1, char *name2)
4062 pstring root1,root2;
4064 char *p,*p2, *pname1, *pname2;
4065 int available_space, actual_space;
4068 pname1 = strrchr_m(name1,'/');
4069 pname2 = strrchr_m(name2,'/');
4071 if (!pname1 || !pname2)
4074 pstrcpy(root1,pname1);
4075 pstrcpy(root2,pname2);
4076 p = strrchr_m(root1,'.');
4083 p = strrchr_m(root2,'.');
4097 } else if (*p2 == '*') {
4113 } else if (*p2 == '*') {
4123 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4126 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4127 if (actual_space >= available_space - 1) {
4128 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4129 actual_space - available_space));
4132 pstrcpy_base(pname2, root2, name2);
4138 /****************************************************************************
4139 Ensure open files have their names updated. Updated to notify other smbd's
4141 ****************************************************************************/
4143 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4144 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4147 BOOL did_rename = False;
4149 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4150 /* fsp_name is a relative path under the fsp. To change this for other
4151 sharepaths we need to manipulate relative paths. */
4152 /* TODO - create the absolute path and manipulate the newname
4153 relative to the sharepath. */
4154 if (fsp->conn != conn) {
4157 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4158 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4159 fsp->fsp_name, newname ));
4160 string_set(&fsp->fsp_name, newname);
4165 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4166 (unsigned int)dev, (double)inode, newname ));
4169 /* Send messages to all smbd's (not ourself) that the name has changed. */
4170 rename_share_filename(lck, conn->connectpath, newname);
4173 /****************************************************************************
4174 We need to check if the source path is a parent directory of the destination
4175 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4176 refuse the rename with a sharing violation. Under UNIX the above call can
4177 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4178 probably need to check that the client is a Windows one before disallowing
4179 this as a UNIX client (one with UNIX extensions) can know the source is a
4180 symlink and make this decision intelligently. Found by an excellent bug
4181 report from <AndyLiebman@aol.com>.
4182 ****************************************************************************/
4184 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4186 const char *psrc = src;
4187 const char *pdst = dest;
4190 if (psrc[0] == '.' && psrc[1] == '/') {
4193 if (pdst[0] == '.' && pdst[1] == '/') {
4196 if ((slen = strlen(psrc)) > strlen(pdst)) {
4199 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4202 /****************************************************************************
4203 Rename an open file - given an fsp.
4204 ****************************************************************************/
4206 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
4208 SMB_STRUCT_STAT sbuf;
4209 BOOL bad_path = False;
4210 pstring newname_last_component;
4211 NTSTATUS error = NT_STATUS_OK;
4214 struct share_mode_lock *lck = NULL;
4217 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
4219 /* Quick check for "." and ".." */
4220 if (!bad_path && newname_last_component[0] == '.') {
4221 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
4222 return NT_STATUS_ACCESS_DENIED;
4225 if (!rcdest && bad_path) {
4226 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4229 /* Ensure newname contains a '/' */
4230 if(strrchr_m(newname,'/') == 0) {
4233 pstrcpy(tmpstr, "./");
4234 pstrcat(tmpstr, newname);
4235 pstrcpy(newname, tmpstr);
4239 * Check for special case with case preserving and not
4240 * case sensitive. If the old last component differs from the original
4241 * last component only by case, then we should allow
4242 * the rename (user is trying to change the case of the
4246 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4247 strequal(newname, fsp->fsp_name)) {
4249 pstring newname_modified_last_component;
4252 * Get the last component of the modified name.
4253 * Note that we guarantee that newname contains a '/'
4256 p = strrchr_m(newname,'/');
4257 pstrcpy(newname_modified_last_component,p+1);
4259 if(strcsequal(newname_modified_last_component,
4260 newname_last_component) == False) {
4262 * Replace the modified last component with
4265 pstrcpy(p+1, newname_last_component);
4270 * If the src and dest names are identical - including case,
4271 * don't do the rename, just return success.
4274 if (strcsequal(fsp->fsp_name, newname)) {
4275 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4277 return NT_STATUS_OK;
4280 dest_exists = vfs_object_exist(conn,newname,NULL);
4282 if(!replace_if_exists && dest_exists) {
4283 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4284 fsp->fsp_name,newname));
4285 return NT_STATUS_OBJECT_NAME_COLLISION;
4288 error = can_rename(conn,newname,attrs,&sbuf);
4290 if (dest_exists && !NT_STATUS_IS_OK(error)) {
4291 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4292 nt_errstr(error), fsp->fsp_name,newname));
4293 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4294 error = NT_STATUS_ACCESS_DENIED;
4298 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4299 return NT_STATUS_ACCESS_DENIED;
4302 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4304 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4305 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4306 fsp->fsp_name,newname));
4307 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4309 return NT_STATUS_OK;
4314 if (errno == ENOTDIR || errno == EISDIR) {
4315 error = NT_STATUS_OBJECT_NAME_COLLISION;
4317 error = map_nt_error_from_unix(errno);
4320 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4321 nt_errstr(error), fsp->fsp_name,newname));
4326 /****************************************************************************
4327 The guts of the rename command, split out so it may be called by the NT SMB
4329 ****************************************************************************/
4331 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
4335 pstring last_component_src;
4336 pstring last_component_dest;
4338 BOOL bad_path_src = False;
4339 BOOL bad_path_dest = False;
4341 NTSTATUS error = NT_STATUS_OK;
4344 SMB_STRUCT_STAT sbuf1, sbuf2;
4345 struct share_mode_lock *lck = NULL;
4347 *directory = *mask = 0;
4352 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4353 if (!rc && bad_path_src) {
4354 if (ms_has_wild(last_component_src))
4355 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4356 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4359 /* Quick check for "." and ".." */
4360 if (last_component_src[0] == '.') {
4361 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4362 return NT_STATUS_OBJECT_NAME_INVALID;
4366 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4368 /* Quick check for "." and ".." */
4369 if (last_component_dest[0] == '.') {
4370 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4371 return NT_STATUS_OBJECT_NAME_INVALID;
4376 * Split the old name into directory and last component
4377 * strings. Note that unix_convert may have stripped off a
4378 * leading ./ from both name and newname if the rename is
4379 * at the root of the share. We need to make sure either both
4380 * name and newname contain a / character or neither of them do
4381 * as this is checked in resolve_wildcards().
4384 p = strrchr_m(name,'/');
4386 pstrcpy(directory,".");
4390 pstrcpy(directory,name);
4392 *p = '/'; /* Replace needed for exceptional test below. */
4396 * We should only check the mangled cache
4397 * here if unix_convert failed. This means
4398 * that the path in 'mask' doesn't exist
4399 * on the file system and so we need to look
4400 * for a possible mangle. This patch from
4401 * Tine Smukavec <valentin.smukavec@hermes.si>.
4404 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4405 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4409 * No wildcards - just process the one file.
4411 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4413 /* Add a terminating '/' to the directory name. */
4414 pstrcat(directory,"/");
4415 pstrcat(directory,mask);
4417 /* Ensure newname contains a '/' also */
4418 if(strrchr_m(newname,'/') == 0) {
4421 pstrcpy(tmpstr, "./");
4422 pstrcat(tmpstr, newname);
4423 pstrcpy(newname, tmpstr);
4426 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4427 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4428 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4429 newname, last_component_dest, is_short_name));
4432 * Check for special case with case preserving and not
4433 * case sensitive, if directory and newname are identical,
4434 * and the old last component differs from the original
4435 * last component only by case, then we should allow
4436 * the rename (user is trying to change the case of the
4439 if((conn->case_sensitive == False) &&
4440 (((conn->case_preserve == True) &&
4441 (is_short_name == False)) ||
4442 ((conn->short_case_preserve == True) &&
4443 (is_short_name == True))) &&
4444 strcsequal(directory, newname)) {
4445 pstring modified_last_component;
4448 * Get the last component of the modified name.
4449 * Note that we guarantee that newname contains a '/'
4452 p = strrchr_m(newname,'/');
4453 pstrcpy(modified_last_component,p+1);
4455 if(strcsequal(modified_last_component,
4456 last_component_dest) == False) {
4458 * Replace the modified last component with
4461 pstrcpy(p+1, last_component_dest);
4465 resolve_wildcards(directory,newname);
4468 * The source object must exist.
4471 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4472 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4473 directory,newname));
4475 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4477 * Must return different errors depending on whether the parent
4478 * directory existed or not.
4481 p = strrchr_m(directory, '/');
4483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4485 if (vfs_object_exist(conn, directory, NULL))
4486 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4487 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4489 error = map_nt_error_from_unix(errno);
4490 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4491 nt_errstr(error), directory,newname));
4496 if (!rcdest && bad_path_dest) {
4497 if (ms_has_wild(last_component_dest))
4498 return NT_STATUS_OBJECT_NAME_INVALID;
4499 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4502 error = can_rename(conn,directory,attrs,&sbuf1);
4504 if (!NT_STATUS_IS_OK(error)) {
4505 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4506 nt_errstr(error), directory,newname));
4511 * If the src and dest names are identical - including case,
4512 * don't do the rename, just return success.
4515 if (strcsequal(directory, newname)) {
4516 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4517 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4518 return NT_STATUS_OK;
4521 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4522 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4523 directory,newname));
4524 return NT_STATUS_OBJECT_NAME_COLLISION;
4527 if (rename_path_prefix_equal(directory, newname)) {
4528 return NT_STATUS_SHARING_VIOLATION;
4531 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4533 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4534 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4535 directory,newname));
4536 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4538 return NT_STATUS_OK;
4542 if (errno == ENOTDIR || errno == EISDIR)
4543 error = NT_STATUS_OBJECT_NAME_COLLISION;
4545 error = map_nt_error_from_unix(errno);
4547 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4548 nt_errstr(error), directory,newname));
4553 * Wildcards - process each file that matches.
4555 struct smb_Dir *dir_hnd = NULL;
4559 if (strequal(mask,"????????.???"))
4562 if (check_name(directory,conn))
4563 dir_hnd = OpenDir(conn, directory, mask, attrs);
4567 error = NT_STATUS_NO_SUCH_FILE;
4568 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4570 while ((dname = ReadDirName(dir_hnd, &offset))) {
4572 BOOL sysdir_entry = False;
4574 pstrcpy(fname,dname);
4576 /* Quick check for "." and ".." */
4577 if (fname[0] == '.') {
4578 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4580 sysdir_entry = True;
4587 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4590 if(!mask_match(fname, mask, conn->case_sensitive))
4594 error = NT_STATUS_OBJECT_NAME_INVALID;
4598 error = NT_STATUS_ACCESS_DENIED;
4599 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4600 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4601 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4602 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4605 error = can_rename(conn,fname,attrs,&sbuf1);
4606 if (!NT_STATUS_IS_OK(error)) {
4607 DEBUG(6,("rename %s refused\n", fname));
4610 pstrcpy(destname,newname);
4612 if (!resolve_wildcards(fname,destname)) {
4613 DEBUG(6,("resolve_wildcards %s %s failed\n",
4618 if (strcsequal(fname,destname)) {
4619 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4620 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4622 error = NT_STATUS_OK;
4626 if (!replace_if_exists &&
4627 vfs_file_exist(conn,destname, NULL)) {
4628 DEBUG(6,("file_exist %s\n", destname));
4629 error = NT_STATUS_OBJECT_NAME_COLLISION;
4633 if (rename_path_prefix_equal(fname, destname)) {
4634 return NT_STATUS_SHARING_VIOLATION;
4637 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4639 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4640 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4642 error = NT_STATUS_OK;
4645 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4650 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4651 if (!rcdest && bad_path_dest) {
4652 if (ms_has_wild(last_component_dest))
4653 return NT_STATUS_OBJECT_NAME_INVALID;
4654 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4659 if (count == 0 && NT_STATUS_IS_OK(error)) {
4660 error = map_nt_error_from_unix(errno);
4666 /****************************************************************************
4668 ****************************************************************************/
4670 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4677 uint32 attrs = SVAL(inbuf,smb_vwv0);
4679 BOOL path_contains_wcard = False;
4681 START_PROFILE(SMBmv);
4683 p = smb_buf(inbuf) + 1;
4684 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
4685 if (!NT_STATUS_IS_OK(status)) {
4687 return ERROR_NT(status);
4690 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4691 if (!NT_STATUS_IS_OK(status)) {
4693 return ERROR_NT(status);
4696 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4697 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4699 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4701 status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard);
4702 if (!NT_STATUS_IS_OK(status)) {
4704 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4705 /* We have re-scheduled this call. */
4708 return ERROR_NT(status);
4712 * Win2k needs a changenotify request response before it will
4713 * update after a rename..
4715 process_pending_change_notify_queue((time_t)0);
4716 outsize = set_message(outbuf,0,0,False);
4722 /*******************************************************************
4723 Copy a file as part of a reply_copy.
4724 ******************************************************************/
4726 BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4727 int count,BOOL target_is_directory, int *err_ret)
4729 SMB_STRUCT_STAT src_sbuf, sbuf2;
4731 files_struct *fsp1,*fsp2;
4734 uint32 new_create_disposition;
4738 pstrcpy(dest,dest1);
4739 if (target_is_directory) {
4740 char *p = strrchr_m(src,'/');
4750 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4754 if (!target_is_directory && count) {
4755 new_create_disposition = FILE_OPEN;
4757 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4758 NULL, NULL, &new_create_disposition, NULL)) {
4763 fsp1 = open_file_ntcreate(conn,src,&src_sbuf,
4765 FILE_SHARE_READ|FILE_SHARE_WRITE,
4768 FILE_ATTRIBUTE_NORMAL,
4776 dosattrs = dos_mode(conn, src, &src_sbuf);
4777 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4778 ZERO_STRUCTP(&sbuf2);
4781 fsp2 = open_file_ntcreate(conn,dest,&sbuf2,
4783 FILE_SHARE_READ|FILE_SHARE_WRITE,
4784 new_create_disposition,
4791 close_file(fsp1,ERROR_CLOSE);
4795 if ((ofun&3) == 1) {
4796 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4797 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4799 * Stop the copy from occurring.
4802 src_sbuf.st_size = 0;
4806 if (src_sbuf.st_size) {
4807 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4810 close_file(fsp1,NORMAL_CLOSE);
4812 /* Ensure the modtime is set correctly on the destination file. */
4813 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4816 * As we are opening fsp1 read-only we only expect
4817 * an error on close on fsp2 if we are out of space.
4818 * Thus we don't look at the error return from the
4821 *err_ret = close_file(fsp2,NORMAL_CLOSE);
4823 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4826 /****************************************************************************
4827 Reply to a file copy.
4828 ****************************************************************************/
4830 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4835 pstring mask,newname;
4838 int error = ERRnoaccess;
4842 int tid2 = SVAL(inbuf,smb_vwv0);
4843 int ofun = SVAL(inbuf,smb_vwv1);
4844 int flags = SVAL(inbuf,smb_vwv2);
4845 BOOL target_is_directory=False;
4846 BOOL bad_path1 = False;
4847 BOOL bad_path2 = False;
4848 BOOL path_contains_wcard1 = False;
4849 BOOL path_contains_wcard2 = False;
4851 SMB_STRUCT_STAT sbuf1, sbuf2;
4853 START_PROFILE(SMBcopy);
4855 *directory = *mask = 0;
4858 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
4859 if (!NT_STATUS_IS_OK(status)) {
4860 END_PROFILE(SMBcopy);
4861 return ERROR_NT(status);
4863 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 END_PROFILE(SMBcopy);
4866 return ERROR_NT(status);
4869 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4871 if (tid2 != conn->cnum) {
4872 /* can't currently handle inter share copies XXXX */
4873 DEBUG(3,("Rejecting inter-share copy\n"));
4874 END_PROFILE(SMBcopy);
4875 return ERROR_DOS(ERRSRV,ERRinvdevice);
4878 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4879 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4881 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4882 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4884 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4886 if ((flags&1) && target_is_directory) {
4887 END_PROFILE(SMBcopy);
4888 return ERROR_DOS(ERRDOS,ERRbadfile);
4891 if ((flags&2) && !target_is_directory) {
4892 END_PROFILE(SMBcopy);
4893 return ERROR_DOS(ERRDOS,ERRbadpath);
4896 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4897 /* wants a tree copy! XXXX */
4898 DEBUG(3,("Rejecting tree copy\n"));
4899 END_PROFILE(SMBcopy);
4900 return ERROR_DOS(ERRSRV,ERRerror);
4903 p = strrchr_m(name,'/');
4905 pstrcpy(directory,"./");
4909 pstrcpy(directory,name);
4914 * We should only check the mangled cache
4915 * here if unix_convert failed. This means
4916 * that the path in 'mask' doesn't exist
4917 * on the file system and so we need to look
4918 * for a possible mangle. This patch from
4919 * Tine Smukavec <valentin.smukavec@hermes.si>.
4922 if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4923 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4925 has_wild = path_contains_wcard1;
4928 pstrcat(directory,"/");
4929 pstrcat(directory,mask);
4930 if (resolve_wildcards(directory,newname) &&
4931 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4935 END_PROFILE(SMBcopy);
4936 return(UNIXERROR(ERRHRD,ERRgeneral));
4939 exists = vfs_file_exist(conn,directory,NULL);
4942 struct smb_Dir *dir_hnd = NULL;
4946 if (strequal(mask,"????????.???"))
4949 if (check_name(directory,conn))
4950 dir_hnd = OpenDir(conn, directory, mask, 0);
4956 while ((dname = ReadDirName(dir_hnd, &offset))) {
4958 pstrcpy(fname,dname);
4960 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4963 if(!mask_match(fname, mask, conn->case_sensitive))
4966 error = ERRnoaccess;
4967 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4968 pstrcpy(destname,newname);
4969 if (resolve_wildcards(fname,destname) &&
4970 copy_file(fname,destname,conn,ofun,
4971 count,target_is_directory,&err))
4973 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4981 /* Error on close... */
4983 END_PROFILE(SMBcopy);
4984 return(UNIXERROR(ERRHRD,ERRgeneral));
4988 END_PROFILE(SMBcopy);
4989 return ERROR_DOS(ERRDOS,error);
4991 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4992 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4994 END_PROFILE(SMBcopy);
4995 return(UNIXERROR(ERRDOS,error));
4999 outsize = set_message(outbuf,1,0,True);
5000 SSVAL(outbuf,smb_vwv0,count);
5002 END_PROFILE(SMBcopy);
5006 /****************************************************************************
5008 ****************************************************************************/
5010 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5018 START_PROFILE(pathworks_setdir);
5021 if (!CAN_SETDIR(snum)) {
5022 END_PROFILE(pathworks_setdir);
5023 return ERROR_DOS(ERRDOS,ERRnoaccess);
5026 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5027 if (!NT_STATUS_IS_OK(status)) {
5028 END_PROFILE(pathworks_setdir);
5029 return ERROR_NT(status);
5032 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
5034 if (strlen(newdir) == 0) {
5037 ok = vfs_directory_exist(conn,newdir,NULL);
5039 set_conn_connectpath(conn,newdir);
5043 END_PROFILE(pathworks_setdir);
5044 return ERROR_DOS(ERRDOS,ERRbadpath);
5047 outsize = set_message(outbuf,0,0,False);
5048 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5050 DEBUG(3,("setdir %s\n", newdir));
5052 END_PROFILE(pathworks_setdir);
5057 #define DBGC_CLASS DBGC_LOCKING
5059 /****************************************************************************
5060 Get a lock pid, dealing with large count requests.
5061 ****************************************************************************/
5063 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5065 if(!large_file_format)
5066 return SVAL(data,SMB_LPID_OFFSET(data_offset));
5068 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5071 /****************************************************************************
5072 Get a lock count, dealing with large count requests.
5073 ****************************************************************************/
5075 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5077 SMB_BIG_UINT count = 0;
5079 if(!large_file_format) {
5080 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5083 #if defined(HAVE_LONGLONG)
5084 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5085 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5086 #else /* HAVE_LONGLONG */
5089 * NT4.x seems to be broken in that it sends large file (64 bit)
5090 * lockingX calls even if the CAP_LARGE_FILES was *not*
5091 * negotiated. For boxes without large unsigned ints truncate the
5092 * lock count by dropping the top 32 bits.
5095 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5096 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5097 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5098 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5099 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5102 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5103 #endif /* HAVE_LONGLONG */
5109 #if !defined(HAVE_LONGLONG)
5110 /****************************************************************************
5111 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5112 ****************************************************************************/
5114 static uint32 map_lock_offset(uint32 high, uint32 low)
5118 uint32 highcopy = high;
5121 * Try and find out how many significant bits there are in high.
5124 for(i = 0; highcopy; i++)
5128 * We use 31 bits not 32 here as POSIX
5129 * lock offsets may not be negative.
5132 mask = (~0) << (31 - i);
5135 return 0; /* Fail. */
5141 #endif /* !defined(HAVE_LONGLONG) */
5143 /****************************************************************************
5144 Get a lock offset, dealing with large offset requests.
5145 ****************************************************************************/
5147 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5149 SMB_BIG_UINT offset = 0;
5153 if(!large_file_format) {
5154 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5157 #if defined(HAVE_LONGLONG)
5158 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5159 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5160 #else /* HAVE_LONGLONG */
5163 * NT4.x seems to be broken in that it sends large file (64 bit)
5164 * lockingX calls even if the CAP_LARGE_FILES was *not*
5165 * negotiated. For boxes without large unsigned ints mangle the
5166 * lock offset by mapping the top 32 bits onto the lower 32.
5169 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5170 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5171 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5174 if((new_low = map_lock_offset(high, low)) == 0) {
5176 return (SMB_BIG_UINT)-1;
5179 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5180 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5181 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5182 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5185 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5186 #endif /* HAVE_LONGLONG */
5192 /****************************************************************************
5193 Reply to a lockingX request.
5194 ****************************************************************************/
5196 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5197 int length, int bufsize)
5199 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5200 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5201 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5202 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5203 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5204 SMB_BIG_UINT count = 0, offset = 0;
5206 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5209 BOOL large_file_format =
5210 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5212 BOOL my_lock_ctx = False;
5213 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5215 START_PROFILE(SMBlockingX);
5217 CHECK_FSP(fsp,conn);
5219 data = smb_buf(inbuf);
5221 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5222 /* we don't support these - and CANCEL_LOCK makes w2k
5223 and XP reboot so I don't really want to be
5224 compatible! (tridge) */
5225 return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks);
5228 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5229 /* Need to make this like a cancel.... JRA. */
5230 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
5233 /* Check if this is an oplock break on a file
5234 we have granted an oplock on.
5236 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5237 /* Client can insist on breaking to none. */
5238 BOOL break_to_none = (oplocklevel == 0);
5241 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5242 "for fnum = %d\n", (unsigned int)oplocklevel,
5246 * Make sure we have granted an exclusive or batch oplock on
5250 if (fsp->oplock_type == 0) {
5252 /* The Samba4 nbench simulator doesn't understand
5253 the difference between break to level2 and break
5254 to none from level2 - it sends oplock break
5255 replies in both cases. Don't keep logging an error
5256 message here - just ignore it. JRA. */
5258 DEBUG(5,("reply_lockingX: Error : oplock break from "
5259 "client for fnum = %d (oplock=%d) and no "
5260 "oplock granted on this file (%s).\n",
5261 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5263 /* if this is a pure oplock break request then don't
5265 if (num_locks == 0 && num_ulocks == 0) {
5266 END_PROFILE(SMBlockingX);
5269 END_PROFILE(SMBlockingX);
5270 return ERROR_DOS(ERRDOS,ERRlock);
5274 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5276 result = remove_oplock(fsp);
5278 result = downgrade_oplock(fsp);
5282 DEBUG(0, ("reply_lockingX: error in removing "
5283 "oplock on file %s\n", fsp->fsp_name));
5284 /* Hmmm. Is this panic justified? */
5285 smb_panic("internal tdb error");
5288 reply_to_oplock_break_requests(fsp);
5290 /* if this is a pure oplock break request then don't send a
5292 if (num_locks == 0 && num_ulocks == 0) {
5293 /* Sanity check - ensure a pure oplock break is not a
5295 if(CVAL(inbuf,smb_vwv0) != 0xff)
5296 DEBUG(0,("reply_lockingX: Error : pure oplock "
5297 "break is a chained %d request !\n",
5298 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5299 END_PROFILE(SMBlockingX);
5305 * We do this check *after* we have checked this is not a oplock break
5306 * response message. JRA.
5309 release_level_2_oplocks_on_change(fsp);
5311 /* Data now points at the beginning of the list
5312 of smb_unlkrng structs */
5313 for(i = 0; i < (int)num_ulocks; i++) {
5314 lock_pid = get_lock_pid( data, i, large_file_format);
5315 count = get_lock_count( data, i, large_file_format);
5316 offset = get_lock_offset( data, i, large_file_format, &err);
5319 * There is no error code marked "stupid client bug".... :-).
5322 END_PROFILE(SMBlockingX);
5323 return ERROR_DOS(ERRDOS,ERRnoaccess);
5326 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5327 "pid %u, file %s\n", (double)offset, (double)count,
5328 (unsigned int)lock_pid, fsp->fsp_name ));
5330 status = do_unlock(fsp,
5336 if (NT_STATUS_V(status)) {
5337 END_PROFILE(SMBlockingX);
5338 return ERROR_NT(status);
5342 /* Setup the timeout in seconds. */
5344 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5346 /* Now do any requested locks */
5347 data += ((large_file_format ? 20 : 10)*num_ulocks);
5349 /* Data now points at the beginning of the list
5350 of smb_lkrng structs */
5352 for(i = 0; i < (int)num_locks; i++) {
5353 enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK);
5354 lock_pid = get_lock_pid( data, i, large_file_format);
5355 count = get_lock_count( data, i, large_file_format);
5356 offset = get_lock_offset( data, i, large_file_format, &err);
5359 * There is no error code marked "stupid client bug".... :-).
5362 END_PROFILE(SMBlockingX);
5363 return ERROR_DOS(ERRDOS,ERRnoaccess);
5366 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5367 "%u, file %s timeout = %d\n", (double)offset,
5368 (double)count, (unsigned int)lock_pid,
5369 fsp->fsp_name, (int)lock_timeout ));
5371 status = do_lock_spin(fsp,
5379 if (NT_STATUS_V(status)) {
5381 * Interesting fact found by IFSTEST /t
5382 * LockOverlappedTest... Even if it's our own lock
5383 * context, we need to wait here as there may be an
5384 * unlock on the way. So I removed a "&&
5385 * !my_lock_ctx" from the following if statement. JRA.
5387 if ((lock_timeout != 0) &&
5388 lp_blocking_locks(SNUM(conn)) &&
5389 ERROR_WAS_LOCK_DENIED(status)) {
5391 * A blocking lock was requested. Package up
5392 * this smb into a queued request and push it
5393 * onto the blocking lock queue.
5395 if(push_blocking_lock_request(inbuf, length,
5404 END_PROFILE(SMBlockingX);
5412 /* If any of the above locks failed, then we must unlock
5413 all of the previous locks (X/Open spec). */
5414 if (i != num_locks && num_locks != 0) {
5416 * Ensure we don't do a remove on the lock that just failed,
5417 * as under POSIX rules, if we have a lock already there, we
5418 * will delete it (and we shouldn't) .....
5420 for(i--; i >= 0; i--) {
5421 lock_pid = get_lock_pid( data, i, large_file_format);
5422 count = get_lock_count( data, i, large_file_format);
5423 offset = get_lock_offset( data, i, large_file_format,
5427 * There is no error code marked "stupid client
5431 END_PROFILE(SMBlockingX);
5432 return ERROR_DOS(ERRDOS,ERRnoaccess);
5441 END_PROFILE(SMBlockingX);
5442 return ERROR_NT(status);
5445 set_message(outbuf,2,0,True);
5447 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5448 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5450 END_PROFILE(SMBlockingX);
5451 return chain_reply(inbuf,outbuf,length,bufsize);
5455 #define DBGC_CLASS DBGC_ALL
5457 /****************************************************************************
5458 Reply to a SMBreadbmpx (read block multiplex) request.
5459 ****************************************************************************/
5461 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5472 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5473 START_PROFILE(SMBreadBmpx);
5475 /* this function doesn't seem to work - disable by default */
5476 if (!lp_readbmpx()) {
5477 END_PROFILE(SMBreadBmpx);
5478 return ERROR_DOS(ERRSRV,ERRuseSTD);
5481 outsize = set_message(outbuf,8,0,True);
5483 CHECK_FSP(fsp,conn);
5484 if (!CHECK_READ(fsp,inbuf)) {
5485 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5488 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5489 maxcount = SVAL(inbuf,smb_vwv3);
5491 data = smb_buf(outbuf);
5492 pad = ((long)data)%4;
5497 max_per_packet = bufsize-(outsize+pad);
5501 if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5502 END_PROFILE(SMBreadBmpx);
5503 return ERROR_DOS(ERRDOS,ERRlock);
5507 size_t N = MIN(max_per_packet,tcount-total_read);
5509 nread = read_file(fsp,data,startpos,N);
5514 if (nread < (ssize_t)N)
5515 tcount = total_read + nread;
5517 set_message(outbuf,8,nread+pad,False);
5518 SIVAL(outbuf,smb_vwv0,startpos);
5519 SSVAL(outbuf,smb_vwv2,tcount);
5520 SSVAL(outbuf,smb_vwv6,nread);
5521 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5524 if (!send_smb(smbd_server_fd(),outbuf))
5525 exit_server("reply_readbmpx: send_smb failed.");
5527 total_read += nread;
5529 } while (total_read < (ssize_t)tcount);
5531 END_PROFILE(SMBreadBmpx);
5535 /****************************************************************************
5536 Reply to a SMBsetattrE.
5537 ****************************************************************************/
5539 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5541 struct utimbuf unix_times;
5543 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5544 START_PROFILE(SMBsetattrE);
5546 outsize = set_message(outbuf,0,0,False);
5548 if(!fsp || (fsp->conn != conn)) {
5549 END_PROFILE(SMBsetattrE);
5550 return ERROR_DOS(ERRDOS,ERRbadfid);
5554 * Convert the DOS times into unix times. Ignore create
5555 * time as UNIX can't set this.
5558 unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
5559 unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
5562 * Patch from Ray Frush <frush@engr.colostate.edu>
5563 * Sometimes times are sent as zero - ignore them.
5566 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5567 /* Ignore request */
5568 if( DEBUGLVL( 3 ) ) {
5569 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5570 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5572 END_PROFILE(SMBsetattrE);
5574 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5575 /* set modify time = to access time if modify time was unset */
5576 unix_times.modtime = unix_times.actime;
5579 /* Set the date on this file */
5580 /* Should we set pending modtime here ? JRA */
5581 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5582 END_PROFILE(SMBsetattrE);
5583 return ERROR_DOS(ERRDOS,ERRnoaccess);
5586 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5587 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5589 END_PROFILE(SMBsetattrE);
5594 /* Back from the dead for OS/2..... JRA. */
5596 /****************************************************************************
5597 Reply to a SMBwritebmpx (write block multiplex primary) request.
5598 ****************************************************************************/
5600 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5603 ssize_t nwritten = -1;
5610 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5611 START_PROFILE(SMBwriteBmpx);
5613 CHECK_FSP(fsp,conn);
5614 if (!CHECK_WRITE(fsp)) {
5615 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5617 if (HAS_CACHED_ERROR(fsp)) {
5618 return(CACHED_ERROR(fsp));
5621 tcount = SVAL(inbuf,smb_vwv1);
5622 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5623 write_through = BITSETW(inbuf+smb_vwv7,0);
5624 numtowrite = SVAL(inbuf,smb_vwv10);
5625 smb_doff = SVAL(inbuf,smb_vwv11);
5627 data = smb_base(inbuf) + smb_doff;
5629 /* If this fails we need to send an SMBwriteC response,
5630 not an SMBwritebmpx - set this up now so we don't forget */
5631 SCVAL(outbuf,smb_com,SMBwritec);
5633 if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5634 END_PROFILE(SMBwriteBmpx);
5635 return(ERROR_DOS(ERRDOS,ERRlock));
5638 nwritten = write_file(fsp,data,startpos,numtowrite);
5640 sync_file(conn, fsp, write_through);
5642 if(nwritten < (ssize_t)numtowrite) {
5643 END_PROFILE(SMBwriteBmpx);
5644 return(UNIXERROR(ERRHRD,ERRdiskfull));
5647 /* If the maximum to be written to this file
5648 is greater than what we just wrote then set
5649 up a secondary struct to be attached to this
5650 fd, we will use this to cache error messages etc. */
5652 if((ssize_t)tcount > nwritten) {
5653 write_bmpx_struct *wbms;
5654 if(fsp->wbmpx_ptr != NULL)
5655 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5657 wbms = SMB_MALLOC_P(write_bmpx_struct);
5659 DEBUG(0,("Out of memory in reply_readmpx\n"));
5660 END_PROFILE(SMBwriteBmpx);
5661 return(ERROR_DOS(ERRSRV,ERRnoresource));
5663 wbms->wr_mode = write_through;
5664 wbms->wr_discard = False; /* No errors yet */
5665 wbms->wr_total_written = nwritten;
5666 wbms->wr_errclass = 0;
5668 fsp->wbmpx_ptr = wbms;
5671 /* We are returning successfully, set the message type back to
5673 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5675 outsize = set_message(outbuf,1,0,True);
5677 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5679 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5680 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5682 if (write_through && tcount==nwritten) {
5683 /* We need to send both a primary and a secondary response */
5684 smb_setlen(outbuf,outsize - 4);
5686 if (!send_smb(smbd_server_fd(),outbuf))
5687 exit_server("reply_writebmpx: send_smb failed.");
5689 /* Now the secondary */
5690 outsize = set_message(outbuf,1,0,True);
5691 SCVAL(outbuf,smb_com,SMBwritec);
5692 SSVAL(outbuf,smb_vwv0,nwritten);
5695 END_PROFILE(SMBwriteBmpx);
5699 /****************************************************************************
5700 Reply to a SMBwritebs (write block multiplex secondary) request.
5701 ****************************************************************************/
5703 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5706 ssize_t nwritten = -1;
5713 write_bmpx_struct *wbms;
5714 BOOL send_response = False;
5715 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5716 START_PROFILE(SMBwriteBs);
5718 CHECK_FSP(fsp,conn);
5719 if (!CHECK_WRITE(fsp)) {
5720 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5723 tcount = SVAL(inbuf,smb_vwv1);
5724 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5725 numtowrite = SVAL(inbuf,smb_vwv6);
5726 smb_doff = SVAL(inbuf,smb_vwv7);
5728 data = smb_base(inbuf) + smb_doff;
5730 /* We need to send an SMBwriteC response, not an SMBwritebs */
5731 SCVAL(outbuf,smb_com,SMBwritec);
5733 /* This fd should have an auxiliary struct attached,
5734 check that it does */
5735 wbms = fsp->wbmpx_ptr;
5737 END_PROFILE(SMBwriteBs);
5741 /* If write through is set we can return errors, else we must cache them */
5742 write_through = wbms->wr_mode;
5744 /* Check for an earlier error */
5745 if(wbms->wr_discard) {
5746 END_PROFILE(SMBwriteBs);
5747 return -1; /* Just discard the packet */
5750 nwritten = write_file(fsp,data,startpos,numtowrite);
5752 sync_file(conn, fsp, write_through);
5754 if (nwritten < (ssize_t)numtowrite) {
5756 /* We are returning an error - we can delete the aux struct */
5759 fsp->wbmpx_ptr = NULL;
5760 END_PROFILE(SMBwriteBs);
5761 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5763 wbms->wr_errclass = ERRHRD;
5764 wbms->wr_error = ERRdiskfull;
5765 wbms->wr_status = NT_STATUS_DISK_FULL;
5766 wbms->wr_discard = True;
5767 END_PROFILE(SMBwriteBs);
5771 /* Increment the total written, if this matches tcount
5772 we can discard the auxiliary struct (hurrah !) and return a writeC */
5773 wbms->wr_total_written += nwritten;
5774 if(wbms->wr_total_written >= tcount) {
5775 if (write_through) {
5776 outsize = set_message(outbuf,1,0,True);
5777 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5778 send_response = True;
5782 fsp->wbmpx_ptr = NULL;
5786 END_PROFILE(SMBwriteBs);
5790 END_PROFILE(SMBwriteBs);
5794 /****************************************************************************
5795 Reply to a SMBgetattrE.
5796 ****************************************************************************/
5798 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5800 SMB_STRUCT_STAT sbuf;
5803 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5804 START_PROFILE(SMBgetattrE);
5806 outsize = set_message(outbuf,11,0,True);
5808 if(!fsp || (fsp->conn != conn)) {
5809 END_PROFILE(SMBgetattrE);
5810 return ERROR_DOS(ERRDOS,ERRbadfid);
5813 /* Do an fstat on this file */
5814 if(fsp_stat(fsp, &sbuf)) {
5815 END_PROFILE(SMBgetattrE);
5816 return(UNIXERROR(ERRDOS,ERRnoaccess));
5819 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5822 * Convert the times into dos times. Set create
5823 * date to be last modify date as UNIX doesn't save
5827 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5828 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5829 /* Should we check pending modtime here ? JRA */
5830 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5833 SIVAL(outbuf,smb_vwv6,0);
5834 SIVAL(outbuf,smb_vwv8,0);
5836 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5837 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5838 SIVAL(outbuf,smb_vwv8,allocation_size);
5840 SSVAL(outbuf,smb_vwv10, mode);
5842 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5844 END_PROFILE(SMBgetattrE);