2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
33 extern int global_oplock_break;
34 unsigned int smb_echo_count = 0;
35 extern uint32 global_client_caps;
37 extern struct current_user current_user;
38 extern BOOL global_encrypted_passwords_negotiated;
40 /****************************************************************************
41 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
50 const char *s = srcname;
51 NTSTATUS ret = NT_STATUS_OK;
52 BOOL start_of_name_component = True;
53 unsigned int num_bad_components = 0;
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
69 start_of_name_component = True;
73 if (start_of_name_component) {
74 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
75 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
78 * No mb char starts with '.' so we're safe checking the directory separator here.
81 /* If we just added a '/' - delete it */
82 if ((d > destname) && (*(d-1) == '/')) {
87 /* Are we at the start ? Can't go back further if so. */
89 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
92 /* Go back one level... */
93 /* We know this is safe as '/' cannot be part of a mb sequence. */
94 /* NOTE - if this assumption is invalid we are not in good shape... */
95 /* Decrement d first as d points to the *next* char to write into. */
96 for (d--; d > destname; d--) {
100 s += 2; /* Else go past the .. */
101 /* We're still at the start of a name component, just the previous one. */
103 if (num_bad_components) {
104 /* Hmmm. Should we only decrement the bad_components if
105 we're removing a bad component ? Need to check this. JRA. */
106 num_bad_components--;
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112 /* Component of pathname can't be "." only. */
113 ret = NT_STATUS_OBJECT_NAME_INVALID;
114 num_bad_components++;
122 return NT_STATUS_OBJECT_NAME_INVALID;
130 return NT_STATUS_OBJECT_NAME_INVALID;
136 switch(next_mb_char_size(s)) {
147 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
149 return NT_STATUS_INVALID_PARAMETER;
152 if (start_of_name_component && num_bad_components) {
153 num_bad_components++;
155 start_of_name_component = False;
158 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
159 if (num_bad_components > 1) {
160 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
168 /****************************************************************************
169 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
170 path or anything including wildcards.
171 We're assuming here that '/' is not the second byte in any multibyte char
172 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
174 ****************************************************************************/
176 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
179 const char *s = srcname;
180 NTSTATUS ret = NT_STATUS_OK;
181 BOOL start_of_name_component = True;
182 unsigned int num_bad_components = 0;
185 if (IS_DIRECTORY_SEP(*s)) {
187 * Safe to assume is not the second part of a mb char as this is handled below.
189 /* Eat multiple '/' or '\\' */
190 while (IS_DIRECTORY_SEP(*s)) {
193 if ((d != destname) && (*s != '\0')) {
194 /* We only care about non-leading or trailing '/' or '\\' */
198 start_of_name_component = True;
202 if (start_of_name_component) {
203 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
204 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
207 * No mb char starts with '.' so we're safe checking the directory separator here.
210 /* If we just added a '/' - delete it */
211 if ((d > destname) && (*(d-1) == '/')) {
216 /* Are we at the start ? Can't go back further if so. */
218 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
221 /* Go back one level... */
222 /* We know this is safe as '/' cannot be part of a mb sequence. */
223 /* NOTE - if this assumption is invalid we are not in good shape... */
224 /* Decrement d first as d points to the *next* char to write into. */
225 for (d--; d > destname; d--) {
229 s += 2; /* Else go past the .. */
230 /* We're still at the start of a name component, just the previous one. */
232 if (num_bad_components) {
233 /* Hmmm. Should we only decrement the bad_components if
234 we're removing a bad component ? Need to check this. JRA. */
235 num_bad_components--;
240 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
241 /* Component of pathname can't be "." only. */
242 ret = NT_STATUS_OBJECT_NAME_INVALID;
243 num_bad_components++;
251 return NT_STATUS_OBJECT_NAME_INVALID;
255 switch(next_mb_char_size(s)) {
266 DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
268 return NT_STATUS_INVALID_PARAMETER;
271 if (start_of_name_component && num_bad_components) {
272 num_bad_components++;
274 start_of_name_component = False;
277 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
278 /* For some strange reason being called from findfirst changes
279 the num_components number to cause the error return to change. JRA. */
280 if (num_bad_components > 2) {
281 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
289 /****************************************************************************
290 Check the path for a POSIX client.
291 We're assuming here that '/' is not the second byte in any multibyte char
292 set (a safe assumption).
293 ****************************************************************************/
295 NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
298 const char *s = srcname;
299 NTSTATUS ret = NT_STATUS_OK;
300 BOOL start_of_name_component = True;
305 * Safe to assume is not the second part of a mb char as this is handled below.
307 /* Eat multiple '/' or '\\' */
311 if ((d != destname) && (*s != '\0')) {
312 /* We only care about non-leading or trailing '/' */
316 start_of_name_component = True;
320 if (start_of_name_component) {
321 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
322 /* Uh oh - "/../" or "/..\0" ! */
325 * No mb char starts with '.' so we're safe checking the directory separator here.
328 /* If we just added a '/' - delete it */
329 if ((d > destname) && (*(d-1) == '/')) {
334 /* Are we at the start ? Can't go back further if so. */
336 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
339 /* Go back one level... */
340 /* We know this is safe as '/' cannot be part of a mb sequence. */
341 /* NOTE - if this assumption is invalid we are not in good shape... */
342 /* Decrement d first as d points to the *next* char to write into. */
343 for (d--; d > destname; d--) {
347 s += 2; /* Else go past the .. */
350 } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
360 switch(next_mb_char_size(s)) {
371 DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
373 return NT_STATUS_INVALID_PARAMETER;
376 start_of_name_component = False;
383 /****************************************************************************
384 Pull a string and check the path - provide for error return.
385 ****************************************************************************/
387 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
390 char *tmppath_ptr = tmppath;
393 SMB_ASSERT(dest_len == sizeof(pstring));
397 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
399 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
401 if (allow_wcard_names) {
402 *err = check_path_syntax_wcard(dest, tmppath);
404 *err = check_path_syntax(dest, tmppath);
409 /****************************************************************************
410 Reply to a special message.
411 ****************************************************************************/
413 int reply_special(char *inbuf,char *outbuf)
416 int msg_type = CVAL(inbuf,0);
417 int msg_flags = CVAL(inbuf,1);
421 static BOOL already_got_session = False;
425 memset(outbuf,'\0',smb_size);
427 smb_setlen(outbuf,0);
430 case 0x81: /* session request */
432 if (already_got_session) {
433 exit_server("multiple session request not permitted");
436 SCVAL(outbuf,0,0x82);
438 if (name_len(inbuf+4) > 50 ||
439 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
440 DEBUG(0,("Invalid name length in session request\n"));
443 name_extract(inbuf,4,name1);
444 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
445 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
448 set_local_machine_name(name1, True);
449 set_remote_machine_name(name2, True);
451 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
452 get_local_machine_name(), get_remote_machine_name(),
455 if (name_type == 'R') {
456 /* We are being asked for a pathworks session ---
458 SCVAL(outbuf, 0,0x83);
462 /* only add the client's machine name to the list
463 of possibly valid usernames if we are operating
464 in share mode security */
465 if (lp_security() == SEC_SHARE) {
466 add_session_user(get_remote_machine_name());
469 reload_services(True);
472 already_got_session = True;
475 case 0x89: /* session keepalive request
476 (some old clients produce this?) */
477 SCVAL(outbuf,0,SMBkeepalive);
481 case 0x82: /* positive session response */
482 case 0x83: /* negative session response */
483 case 0x84: /* retarget session response */
484 DEBUG(0,("Unexpected session response\n"));
487 case SMBkeepalive: /* session keepalive */
492 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
493 msg_type, msg_flags));
498 /****************************************************************************
500 ****************************************************************************/
502 int reply_tcon(connection_struct *conn,
503 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
510 uint16 vuid = SVAL(inbuf,smb_uid);
514 DATA_BLOB password_blob;
516 START_PROFILE(SMBtcon);
518 *service_buf = *password = *dev = 0;
520 p = smb_buf(inbuf)+1;
521 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
522 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
524 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
526 p = strrchr_m(service_buf,'\\');
530 service = service_buf;
533 password_blob = data_blob(password, pwlen+1);
535 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
537 data_blob_clear_free(&password_blob);
540 END_PROFILE(SMBtcon);
541 return ERROR_NT(nt_status);
544 outsize = set_message(outbuf,2,0,True);
545 SSVAL(outbuf,smb_vwv0,max_recv);
546 SSVAL(outbuf,smb_vwv1,conn->cnum);
547 SSVAL(outbuf,smb_tid,conn->cnum);
549 DEBUG(3,("tcon service=%s cnum=%d\n",
550 service, conn->cnum));
552 END_PROFILE(SMBtcon);
556 /****************************************************************************
557 Reply to a tcon and X.
558 ****************************************************************************/
560 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
565 /* what the cleint thinks the device is */
566 fstring client_devicetype;
567 /* what the server tells the client the share represents */
568 const char *server_devicetype;
570 uint16 vuid = SVAL(inbuf,smb_uid);
571 int passlen = SVAL(inbuf,smb_vwv3);
575 START_PROFILE(SMBtconX);
577 *service = *client_devicetype = 0;
579 /* we might have to close an old one */
580 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
581 close_cnum(conn,vuid);
584 if (passlen > MAX_PASS_LEN) {
585 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
588 if (global_encrypted_passwords_negotiated) {
589 password = data_blob(smb_buf(inbuf),passlen);
591 password = data_blob(smb_buf(inbuf),passlen+1);
592 /* Ensure correct termination */
593 password.data[passlen]=0;
596 p = smb_buf(inbuf) + passlen;
597 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
600 * the service name can be either: \\server\share
601 * or share directly like on the DELL PowerVault 705
604 q = strchr_m(path+2,'\\');
606 END_PROFILE(SMBtconX);
607 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
609 fstrcpy(service,q+1);
612 fstrcpy(service,path);
614 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
616 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
618 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
620 data_blob_clear_free(&password);
623 END_PROFILE(SMBtconX);
624 return ERROR_NT(nt_status);
628 server_devicetype = "IPC";
629 else if ( IS_PRINT(conn) )
630 server_devicetype = "LPT1:";
632 server_devicetype = "A:";
634 if (Protocol < PROTOCOL_NT1) {
635 set_message(outbuf,2,0,True);
637 p += srvstr_push(outbuf, p, server_devicetype, -1,
638 STR_TERMINATE|STR_ASCII);
639 set_message_end(outbuf,p);
641 /* NT sets the fstype of IPC$ to the null string */
642 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
644 set_message(outbuf,3,0,True);
647 p += srvstr_push(outbuf, p, server_devicetype, -1,
648 STR_TERMINATE|STR_ASCII);
649 p += srvstr_push(outbuf, p, fstype, -1,
652 set_message_end(outbuf,p);
654 /* what does setting this bit do? It is set by NT4 and
655 may affect the ability to autorun mounted cdroms */
656 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
657 (lp_csc_policy(SNUM(conn)) << 2));
659 init_dfsroot(conn, inbuf, outbuf);
663 DEBUG(3,("tconX service=%s \n",
666 /* set the incoming and outgoing tid to the just created one */
667 SSVAL(inbuf,smb_tid,conn->cnum);
668 SSVAL(outbuf,smb_tid,conn->cnum);
670 END_PROFILE(SMBtconX);
671 return chain_reply(inbuf,outbuf,length,bufsize);
674 /****************************************************************************
675 Reply to an unknown type.
676 ****************************************************************************/
678 int reply_unknown(char *inbuf,char *outbuf)
681 type = CVAL(inbuf,smb_com);
683 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
684 smb_fn_name(type), type, type));
686 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
689 /****************************************************************************
691 ****************************************************************************/
693 int reply_ioctl(connection_struct *conn,
694 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
696 uint16 device = SVAL(inbuf,smb_vwv1);
697 uint16 function = SVAL(inbuf,smb_vwv2);
698 uint32 ioctl_code = (device << 16) + function;
699 int replysize, outsize;
701 START_PROFILE(SMBioctl);
703 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
705 switch (ioctl_code) {
706 case IOCTL_QUERY_JOB_INFO:
710 END_PROFILE(SMBioctl);
711 return(ERROR_DOS(ERRSRV,ERRnosupport));
714 outsize = set_message(outbuf,8,replysize+1,True);
715 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
716 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
717 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
718 p = smb_buf(outbuf) + 1; /* Allow for alignment */
720 switch (ioctl_code) {
721 case IOCTL_QUERY_JOB_INFO:
723 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
725 END_PROFILE(SMBioctl);
726 return(UNIXERROR(ERRDOS,ERRbadfid));
728 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
729 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
731 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
737 END_PROFILE(SMBioctl);
741 /****************************************************************************
743 ****************************************************************************/
745 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
750 BOOL bad_path = False;
751 SMB_STRUCT_STAT sbuf;
754 START_PROFILE(SMBchkpth);
756 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
757 if (!NT_STATUS_IS_OK(status)) {
758 END_PROFILE(SMBchkpth);
759 return ERROR_NT(status);
762 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
764 unix_convert(name,conn,0,&bad_path,&sbuf);
766 END_PROFILE(SMBchkpth);
767 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
770 if (check_name(name,conn)) {
771 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
772 if (!(ok = S_ISDIR(sbuf.st_mode))) {
773 END_PROFILE(SMBchkpth);
774 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
779 /* We special case this - as when a Windows machine
780 is parsing a path is steps through the components
781 one at a time - if a component fails it expects
782 ERRbadpath, not ERRbadfile.
784 if(errno == ENOENT) {
786 * Windows returns different error codes if
787 * the parent directory is valid but not the
788 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
789 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
790 * if the path is invalid. This is different from set_bad_path_error()
791 * in the non-NT error case.
793 END_PROFILE(SMBchkpth);
794 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
797 END_PROFILE(SMBchkpth);
798 return(UNIXERROR(ERRDOS,ERRbadpath));
801 outsize = set_message(outbuf,0,0,True);
802 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
804 END_PROFILE(SMBchkpth);
808 /****************************************************************************
810 ****************************************************************************/
812 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
816 SMB_STRUCT_STAT sbuf;
821 BOOL bad_path = False;
825 START_PROFILE(SMBgetatr);
827 p = smb_buf(inbuf) + 1;
828 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
829 if (!NT_STATUS_IS_OK(status)) {
830 END_PROFILE(SMBgetatr);
831 return ERROR_NT(status);
834 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
836 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
837 under WfWg - weird! */
839 mode = aHIDDEN | aDIR;
840 if (!CAN_WRITE(conn))
846 unix_convert(fname,conn,0,&bad_path,&sbuf);
848 END_PROFILE(SMBgetatr);
849 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
851 if (check_name(fname,conn)) {
852 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
853 mode = dos_mode(conn,fname,&sbuf);
855 mtime = sbuf.st_mtime;
860 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
866 END_PROFILE(SMBgetatr);
867 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
870 outsize = set_message(outbuf,10,0,True);
872 SSVAL(outbuf,smb_vwv0,mode);
873 if(lp_dos_filetime_resolution(SNUM(conn)) )
874 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
876 put_dos_date3(outbuf,smb_vwv1,mtime);
877 SIVAL(outbuf,smb_vwv3,(uint32)size);
879 if (Protocol >= PROTOCOL_NT1)
880 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
882 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
884 END_PROFILE(SMBgetatr);
888 /****************************************************************************
890 ****************************************************************************/
892 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
899 SMB_STRUCT_STAT sbuf;
900 BOOL bad_path = False;
904 START_PROFILE(SMBsetatr);
906 p = smb_buf(inbuf) + 1;
907 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
908 if (!NT_STATUS_IS_OK(status)) {
909 END_PROFILE(SMBsetatr);
910 return ERROR_NT(status);
913 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
915 unix_convert(fname,conn,0,&bad_path,&sbuf);
917 END_PROFILE(SMBsetatr);
918 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
921 mode = SVAL(inbuf,smb_vwv0);
922 mtime = make_unix_date3(inbuf+smb_vwv1);
924 if (mode != FILE_ATTRIBUTE_NORMAL) {
925 if (VALID_STAT_OF_DIR(sbuf))
930 if (check_name(fname,conn)) {
931 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
938 ok = set_filetime(conn,fname,mtime);
941 END_PROFILE(SMBsetatr);
942 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
945 outsize = set_message(outbuf,0,0,True);
947 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
949 END_PROFILE(SMBsetatr);
953 /****************************************************************************
955 ****************************************************************************/
957 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
960 SMB_BIG_UINT dfree,dsize,bsize;
961 START_PROFILE(SMBdskattr);
963 if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
964 END_PROFILE(SMBdskattr);
965 return(UNIXERROR(ERRHRD,ERRgeneral));
968 outsize = set_message(outbuf,5,0,True);
970 if (Protocol <= PROTOCOL_LANMAN2) {
971 double total_space, free_space;
972 /* we need to scale this to a number that DOS6 can handle. We
973 use floating point so we can handle large drives on systems
974 that don't have 64 bit integers
976 we end up displaying a maximum of 2G to DOS systems
978 total_space = dsize * (double)bsize;
979 free_space = dfree * (double)bsize;
981 dsize = (total_space+63*512) / (64*512);
982 dfree = (free_space+63*512) / (64*512);
984 if (dsize > 0xFFFF) dsize = 0xFFFF;
985 if (dfree > 0xFFFF) dfree = 0xFFFF;
987 SSVAL(outbuf,smb_vwv0,dsize);
988 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
989 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
990 SSVAL(outbuf,smb_vwv3,dfree);
992 SSVAL(outbuf,smb_vwv0,dsize);
993 SSVAL(outbuf,smb_vwv1,bsize/512);
994 SSVAL(outbuf,smb_vwv2,512);
995 SSVAL(outbuf,smb_vwv3,dfree);
998 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1000 END_PROFILE(SMBdskattr);
1004 /****************************************************************************
1006 Can be called from SMBsearch, SMBffirst or SMBfunique.
1007 ****************************************************************************/
1009 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1019 unsigned int numentries = 0;
1020 unsigned int maxentries = 0;
1021 BOOL finished = False;
1028 BOOL check_descend = False;
1029 BOOL expect_close = False;
1030 BOOL can_open = True;
1031 BOOL bad_path = False;
1033 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1035 START_PROFILE(SMBsearch);
1037 *mask = *directory = *fname = 0;
1039 /* If we were called as SMBffirst then we must expect close. */
1040 if(CVAL(inbuf,smb_com) == SMBffirst)
1041 expect_close = True;
1043 outsize = set_message(outbuf,1,3,True);
1044 maxentries = SVAL(inbuf,smb_vwv0);
1045 dirtype = SVAL(inbuf,smb_vwv1);
1046 p = smb_buf(inbuf) + 1;
1047 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
1048 if (!NT_STATUS_IS_OK(nt_status)) {
1049 END_PROFILE(SMBsearch);
1050 return ERROR_NT(nt_status);
1053 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
1056 status_len = SVAL(p, 0);
1059 /* dirtype &= ~aDIR; */
1061 if (status_len == 0) {
1062 SMB_STRUCT_STAT sbuf;
1065 pstrcpy(directory,path);
1067 unix_convert(directory,conn,0,&bad_path,&sbuf);
1070 if (!check_name(directory,conn))
1073 p = strrchr_m(dir2,'/');
1082 p = strrchr_m(directory,'/');
1088 if (strlen(directory) == 0)
1089 pstrcpy(directory,".");
1090 memset((char *)status,'\0',21);
1091 SCVAL(status,0,(dirtype & 0x1F));
1095 memcpy(status,p,21);
1096 status_dirtype = CVAL(status,0) & 0x1F;
1097 if (status_dirtype != (dirtype & 0x1F))
1098 dirtype = status_dirtype;
1100 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1103 string_set(&conn->dirpath,dptr_path(dptr_num));
1104 pstrcpy(mask, dptr_wcard(dptr_num));
1108 p = smb_buf(outbuf) + 3;
1111 if (status_len == 0) {
1112 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1114 if(dptr_num == -2) {
1115 END_PROFILE(SMBsearch);
1116 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1118 END_PROFILE(SMBsearch);
1119 return ERROR_DOS(ERRDOS,ERRnofids);
1121 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1122 END_PROFILE(SMBsearch);
1123 return ERROR_DOS(ERRDOS,ERRnomem);
1126 dirtype = dptr_attr(dptr_num);
1129 DEBUG(4,("dptr_num is %d\n",dptr_num));
1132 if ((dirtype&0x1F) == aVOLID) {
1133 memcpy(p,status,21);
1134 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1135 0,aVOLID,0,!allow_long_path_components);
1136 dptr_fill(p+12,dptr_num);
1137 if (dptr_zero(p+12) && (status_len==0))
1141 p += DIR_STRUCT_SIZE;
1144 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1146 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1147 conn->dirpath,lp_dontdescend(SNUM(conn))));
1148 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1149 check_descend = True;
1151 for (i=numentries;(i<maxentries) && !finished;i++) {
1152 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1154 memcpy(p,status,21);
1155 make_dir_struct(p,mask,fname,size, mode,date,
1156 !allow_long_path_components);
1157 dptr_fill(p+12,dptr_num);
1159 p += DIR_STRUCT_SIZE;
1169 /* If we were called as SMBffirst with smb_search_id == NULL
1170 and no entries were found then return error and close dirptr
1173 if (numentries == 0 || !ok) {
1174 dptr_close(&dptr_num);
1175 } else if(ok && expect_close && status_len == 0) {
1176 /* Close the dptr - we know it's gone */
1177 dptr_close(&dptr_num);
1180 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1181 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1182 dptr_close(&dptr_num);
1185 if ((numentries == 0) && !ms_has_wild(mask)) {
1186 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1189 SSVAL(outbuf,smb_vwv0,numentries);
1190 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1191 SCVAL(smb_buf(outbuf),0,5);
1192 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1194 /* The replies here are never long name. */
1195 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1196 if (!allow_long_path_components) {
1197 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1200 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1201 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1203 outsize += DIR_STRUCT_SIZE*numentries;
1204 smb_setlen(outbuf,outsize - 4);
1206 if ((! *directory) && dptr_path(dptr_num))
1207 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1209 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1210 smb_fn_name(CVAL(inbuf,smb_com)),
1211 mask, directory, dirtype, numentries, maxentries ) );
1213 END_PROFILE(SMBsearch);
1217 /****************************************************************************
1218 Reply to a fclose (stop directory search).
1219 ****************************************************************************/
1221 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1231 START_PROFILE(SMBfclose);
1233 outsize = set_message(outbuf,1,0,True);
1234 p = smb_buf(inbuf) + 1;
1235 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1236 if (!NT_STATUS_IS_OK(err)) {
1237 END_PROFILE(SMBfclose);
1238 return ERROR_NT(err);
1241 status_len = SVAL(p,0);
1244 if (status_len == 0) {
1245 END_PROFILE(SMBfclose);
1246 return ERROR_DOS(ERRSRV,ERRsrverror);
1249 memcpy(status,p,21);
1251 if(dptr_fetch(status+12,&dptr_num)) {
1252 /* Close the dptr - we know it's gone */
1253 dptr_close(&dptr_num);
1256 SSVAL(outbuf,smb_vwv0,0);
1258 DEBUG(3,("search close\n"));
1260 END_PROFILE(SMBfclose);
1264 /****************************************************************************
1266 ****************************************************************************/
1268 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1277 SMB_STRUCT_STAT sbuf;
1278 BOOL bad_path = False;
1280 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1281 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1283 START_PROFILE(SMBopen);
1285 share_mode = SVAL(inbuf,smb_vwv0);
1287 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 END_PROFILE(SMBopen);
1290 return ERROR_NT(status);
1293 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1295 unix_convert(fname,conn,0,&bad_path,&sbuf);
1297 END_PROFILE(SMBopen);
1298 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1301 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1302 (uint32)dos_attr, oplock_request,&rmode,NULL);
1305 END_PROFILE(SMBopen);
1306 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1307 /* We have re-scheduled this call. */
1310 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1313 size = sbuf.st_size;
1314 fmode = dos_mode(conn,fname,&sbuf);
1315 mtime = sbuf.st_mtime;
1318 DEBUG(3,("attempt to open a directory %s\n",fname));
1319 close_file(fsp,False);
1320 END_PROFILE(SMBopen);
1321 return ERROR_DOS(ERRDOS,ERRnoaccess);
1324 outsize = set_message(outbuf,7,0,True);
1325 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1326 SSVAL(outbuf,smb_vwv1,fmode);
1327 if(lp_dos_filetime_resolution(SNUM(conn)) )
1328 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1330 put_dos_date3(outbuf,smb_vwv2,mtime);
1331 SIVAL(outbuf,smb_vwv4,(uint32)size);
1332 SSVAL(outbuf,smb_vwv6,rmode);
1334 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1335 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1337 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1338 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1339 END_PROFILE(SMBopen);
1343 /****************************************************************************
1344 Reply to an open and X.
1345 ****************************************************************************/
1347 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1350 int smb_mode = SVAL(inbuf,smb_vwv3);
1351 int smb_attr = SVAL(inbuf,smb_vwv5);
1352 /* Breakout the oplock request bits so we can set the
1353 reply bits separately. */
1354 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1355 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1356 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1358 int open_flags = SVAL(inbuf,smb_vwv2);
1359 int smb_sattr = SVAL(inbuf,smb_vwv4);
1360 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1362 int smb_ofun = SVAL(inbuf,smb_vwv8);
1364 int fmode=0,mtime=0,rmode=0;
1365 SMB_STRUCT_STAT sbuf;
1367 BOOL bad_path = False;
1370 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1371 ssize_t retval = -1;
1373 START_PROFILE(SMBopenX);
1375 /* If it's an IPC, pass off the pipe handler. */
1377 if (lp_nt_pipe_support()) {
1378 END_PROFILE(SMBopenX);
1379 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1381 END_PROFILE(SMBopenX);
1382 return ERROR_DOS(ERRSRV,ERRaccess);
1386 /* XXXX we need to handle passed times, sattr and flags */
1387 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 END_PROFILE(SMBopenX);
1390 return ERROR_NT(status);
1393 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1395 unix_convert(fname,conn,0,&bad_path,&sbuf);
1397 END_PROFILE(SMBopenX);
1398 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1401 /* Strange open mode mapping. */
1402 if (smb_ofun == 0) {
1403 if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) {
1404 smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
1406 END_PROFILE(SMBopenX);
1407 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1411 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1412 oplock_request, &rmode,&smb_action);
1415 END_PROFILE(SMBopenX);
1416 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1417 /* We have re-scheduled this call. */
1420 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1423 size = sbuf.st_size;
1425 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1426 if the file is truncated or created. */
1427 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1428 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1429 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1430 close_file(fsp,False);
1431 END_PROFILE(SMBntcreateX);
1432 return ERROR_NT(NT_STATUS_DISK_FULL);
1434 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1436 close_file(fsp,False);
1437 END_PROFILE(SMBwrite);
1438 return ERROR_NT(NT_STATUS_DISK_FULL);
1440 size = get_allocation_size(conn,fsp,&sbuf);
1443 fmode = dos_mode(conn,fname,&sbuf);
1444 mtime = sbuf.st_mtime;
1446 close_file(fsp,False);
1447 END_PROFILE(SMBopenX);
1448 return ERROR_DOS(ERRDOS,ERRnoaccess);
1451 /* If the caller set the extended oplock request bit
1452 and we granted one (by whatever means) - set the
1453 correct bit for extended oplock reply.
1456 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1457 smb_action |= EXTENDED_OPLOCK_GRANTED;
1459 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1460 smb_action |= EXTENDED_OPLOCK_GRANTED;
1462 /* If the caller set the core oplock request bit
1463 and we granted one (by whatever means) - set the
1464 correct bit for core oplock reply.
1467 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1468 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1470 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1471 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1473 set_message(outbuf,15,0,True);
1474 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1475 SSVAL(outbuf,smb_vwv3,fmode);
1476 if(lp_dos_filetime_resolution(SNUM(conn)) )
1477 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1479 put_dos_date3(outbuf,smb_vwv4,mtime);
1480 SIVAL(outbuf,smb_vwv6,(uint32)size);
1481 SSVAL(outbuf,smb_vwv8,rmode);
1482 SSVAL(outbuf,smb_vwv11,smb_action);
1484 END_PROFILE(SMBopenX);
1485 return chain_reply(inbuf,outbuf,length,bufsize);
1488 /****************************************************************************
1489 Reply to a SMBulogoffX.
1490 ****************************************************************************/
1492 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1494 uint16 vuid = SVAL(inbuf,smb_uid);
1495 user_struct *vuser = get_valid_user_struct(vuid);
1496 START_PROFILE(SMBulogoffX);
1499 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1501 /* in user level security we are supposed to close any files
1502 open by this user */
1503 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1504 file_close_user(vuid);
1506 invalidate_vuid(vuid);
1508 set_message(outbuf,2,0,True);
1510 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1512 END_PROFILE(SMBulogoffX);
1513 return chain_reply(inbuf,outbuf,length,bufsize);
1516 /****************************************************************************
1517 Reply to a mknew or a create.
1518 ****************************************************************************/
1520 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1527 BOOL bad_path = False;
1529 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1530 SMB_STRUCT_STAT sbuf;
1532 START_PROFILE(SMBcreate);
1534 com = SVAL(inbuf,smb_com);
1536 createmode = SVAL(inbuf,smb_vwv0);
1537 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 END_PROFILE(SMBcreate);
1540 return ERROR_NT(status);
1543 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1545 unix_convert(fname,conn,0,&bad_path,&sbuf);
1547 END_PROFILE(SMBcreate);
1548 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1551 if (createmode & aVOLID)
1552 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1554 if(com == SMBmknew) {
1555 /* We should fail if file exists. */
1556 ofun = FILE_CREATE_IF_NOT_EXIST;
1558 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1559 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1562 /* Open file in dos compatibility share mode. */
1563 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1564 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1567 END_PROFILE(SMBcreate);
1568 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1569 /* We have re-scheduled this call. */
1572 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1575 outsize = set_message(outbuf,1,0,True);
1576 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1578 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1579 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1581 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1582 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1584 DEBUG( 2, ( "new file %s\n", fname ) );
1585 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1587 END_PROFILE(SMBcreate);
1591 /****************************************************************************
1592 Reply to a create temporary file.
1593 ****************************************************************************/
1595 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1600 BOOL bad_path = False;
1602 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1604 SMB_STRUCT_STAT sbuf;
1607 unsigned int namelen;
1609 START_PROFILE(SMBctemp);
1611 createattr = SVAL(inbuf,smb_vwv0);
1612 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 END_PROFILE(SMBctemp);
1615 return ERROR_NT(status);
1618 pstrcat(fname,"/TMXXXXXX");
1620 pstrcat(fname,"TMXXXXXX");
1623 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1625 unix_convert(fname,conn,0,&bad_path,&sbuf);
1627 END_PROFILE(SMBctemp);
1628 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1631 tmpfd = smb_mkstemp(fname);
1633 END_PROFILE(SMBctemp);
1634 return(UNIXERROR(ERRDOS,ERRnoaccess));
1637 SMB_VFS_STAT(conn,fname,&sbuf);
1639 /* Open file in dos compatibility share mode. */
1640 /* We should fail if file does not exist. */
1641 fsp = open_file_shared(conn,fname,&sbuf,
1642 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1643 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1644 (uint32)createattr, oplock_request, NULL, NULL);
1646 /* close fd from smb_mkstemp() */
1650 END_PROFILE(SMBctemp);
1651 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1652 /* We have re-scheduled this call. */
1655 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1658 outsize = set_message(outbuf,1,0,True);
1659 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1661 /* the returned filename is relative to the directory */
1662 s = strrchr_m(fname, '/');
1668 p = smb_buf(outbuf);
1670 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1671 thing in the byte section. JRA */
1672 SSVALS(p, 0, -1); /* what is this? not in spec */
1674 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1676 outsize = set_message_end(outbuf, p);
1678 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1679 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1681 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1682 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1684 DEBUG( 2, ( "created temp file %s\n", fname ) );
1685 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1686 fname, fsp->fd, sbuf.st_mode ) );
1688 END_PROFILE(SMBctemp);
1692 /*******************************************************************
1693 Check if a user is allowed to rename a file.
1694 ********************************************************************/
1696 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1703 if (!CAN_WRITE(conn))
1704 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1706 fmode = dos_mode(conn,fname,pst);
1707 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1708 return NT_STATUS_NO_SUCH_FILE;
1710 if (S_ISDIR(pst->st_mode))
1711 return NT_STATUS_OK;
1713 /* We need a better way to return NT status codes from open... */
1714 set_saved_error_triple(0, 0, NT_STATUS_OK);
1716 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1717 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1721 if (get_saved_error_triple(NULL, NULL, &ret)) {
1722 set_saved_error_triple(0, 0, NT_STATUS_OK);
1725 set_saved_error_triple(0, 0, NT_STATUS_OK);
1726 return NT_STATUS_ACCESS_DENIED;
1728 close_file(fsp,False);
1729 return NT_STATUS_OK;
1732 /*******************************************************************
1733 Check if a user is allowed to delete a file.
1734 ********************************************************************/
1736 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1738 SMB_STRUCT_STAT sbuf;
1744 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1747 if (!CAN_WRITE(conn))
1748 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1750 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1751 if(errno == ENOENT) {
1753 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1755 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1757 return map_nt_error_from_unix(errno);
1760 fmode = dos_mode(conn,fname,&sbuf);
1762 /* Can't delete a directory. */
1764 return NT_STATUS_FILE_IS_A_DIRECTORY;
1766 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1767 return NT_STATUS_OBJECT_NAME_INVALID;
1768 #endif /* JRATEST */
1770 if (!lp_delete_readonly(SNUM(conn))) {
1772 return NT_STATUS_CANNOT_DELETE;
1774 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1775 return NT_STATUS_NO_SUCH_FILE;
1777 if (check_is_at_open) {
1778 if (!can_delete_file_in_directory(conn, fname)) {
1779 return NT_STATUS_ACCESS_DENIED;
1782 /* On open checks the open itself will check the share mode, so
1783 don't do it here as we'll get it wrong. */
1785 /* We need a better way to return NT status codes from open... */
1786 set_saved_error_triple(0, 0, NT_STATUS_OK);
1788 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1789 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1793 if (get_saved_error_triple(NULL, NULL, &ret)) {
1794 set_saved_error_triple(0, 0, NT_STATUS_OK);
1797 set_saved_error_triple(0, 0, NT_STATUS_OK);
1798 return NT_STATUS_ACCESS_DENIED;
1800 close_file(fsp,False);
1802 return NT_STATUS_OK;
1805 /****************************************************************************
1806 The guts of the unlink command, split out so it may be called by the NT SMB
1808 ****************************************************************************/
1810 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1816 NTSTATUS error = NT_STATUS_OK;
1818 BOOL bad_path = False;
1820 SMB_STRUCT_STAT sbuf;
1822 *directory = *mask = 0;
1824 /* We must check for wildcards in the name given
1825 * directly by the client - before any unmangling.
1826 * This prevents an unmangling of a UNIX name containing
1827 * a DOS wildcard like '*' or '?' from unmangling into
1828 * a wildcard delete which was not intended.
1829 * FIX for #226. JRA.
1832 has_wild = ms_has_wild(name);
1834 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1836 p = strrchr_m(name,'/');
1838 pstrcpy(directory,".");
1842 pstrcpy(directory,name);
1847 * We should only check the mangled cache
1848 * here if unix_convert failed. This means
1849 * that the path in 'mask' doesn't exist
1850 * on the file system and so we need to look
1851 * for a possible mangle. This patch from
1852 * Tine Smukavec <valentin.smukavec@hermes.si>.
1855 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
1856 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
1859 pstrcat(directory,"/");
1860 pstrcat(directory,mask);
1861 error = can_delete(conn,directory,dirtype,bad_path,False);
1862 if (!NT_STATUS_IS_OK(error))
1865 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1869 struct smb_Dir *dir_hnd = NULL;
1872 if (check_name(directory,conn))
1873 dir_hnd = OpenDir(conn, directory);
1875 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1876 the pattern matches against the long name, otherwise the short name
1877 We don't implement this yet XXXX
1882 error = NT_STATUS_NO_SUCH_FILE;
1884 if (strequal(mask,"????????.???"))
1887 while ((dname = ReadDirName(dir_hnd, &offset))) {
1890 BOOL sys_direntry = False;
1891 pstrcpy(fname,dname);
1893 if (!is_visible_file(conn, directory, dname, &st, True)) {
1897 /* Quick check for "." and ".." */
1898 if (fname[0] == '.') {
1899 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1900 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1901 sys_direntry = True;
1908 if(!mask_match(fname, mask, conn->case_sensitive))
1912 error = NT_STATUS_OBJECT_NAME_INVALID;
1913 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1918 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1919 error = can_delete(conn,fname,dirtype,bad_path,False);
1920 if (!NT_STATUS_IS_OK(error)) {
1923 if (SMB_VFS_UNLINK(conn,fname) == 0)
1925 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1931 if (count == 0 && NT_STATUS_IS_OK(error)) {
1932 error = map_nt_error_from_unix(errno);
1938 /****************************************************************************
1940 ****************************************************************************/
1942 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1949 START_PROFILE(SMBunlink);
1951 dirtype = SVAL(inbuf,smb_vwv0);
1953 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1954 if (!NT_STATUS_IS_OK(status)) {
1955 END_PROFILE(SMBunlink);
1956 return ERROR_NT(status);
1959 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1961 DEBUG(3,("reply_unlink : %s\n",name));
1963 status = unlink_internals(conn, dirtype, name);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1966 /* We have re-scheduled this call. */
1969 return ERROR_NT(status);
1973 * Win2k needs a changenotify request response before it will
1974 * update after a rename..
1976 process_pending_change_notify_queue((time_t)0);
1978 outsize = set_message(outbuf,0,0,True);
1980 END_PROFILE(SMBunlink);
1984 /****************************************************************************
1986 ****************************************************************************/
1988 static void fail_readraw(void)
1991 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1993 exit_server(errstr);
1996 #if defined(WITH_SENDFILE)
1997 /****************************************************************************
1998 Fake (read/write) sendfile. Returns -1 on read or write fail.
1999 ****************************************************************************/
2001 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2005 /* Paranioa check... */
2006 if (nread > bufsize) {
2011 ret = read_file(fsp,buf,startpos,nread);
2017 /* If we had a short read, fill with zeros. */
2019 memset(buf, '\0', nread - ret);
2022 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2026 return (ssize_t)nread;
2030 /****************************************************************************
2031 Use sendfile in readbraw.
2032 ****************************************************************************/
2034 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2035 ssize_t mincount, char *outbuf, int out_buffsize)
2039 #if defined(WITH_SENDFILE)
2041 * We can only use sendfile on a non-chained packet
2042 * but we can use on a non-oplocked file. tridge proved this
2043 * on a train in Germany :-). JRA.
2044 * reply_readbraw has already checked the length.
2047 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
2050 _smb_setlen(outbuf,nread);
2051 header.data = outbuf;
2055 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
2056 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2057 if (errno == ENOSYS) {
2058 goto normal_readbraw;
2062 * Special hack for broken Linux with no working sendfile. If we
2063 * return EINTR we sent the header but not the rest of the data.
2064 * Fake this up by doing read/write calls.
2066 if (errno == EINTR) {
2067 /* Ensure we don't do this again. */
2068 set_use_sendfile(SNUM(conn), False);
2069 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2071 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2072 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2073 fsp->fsp_name, strerror(errno) ));
2074 exit_server("send_file_readbraw fake_sendfile failed");
2079 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2080 fsp->fsp_name, strerror(errno) ));
2081 exit_server("send_file_readbraw sendfile failed");
2091 ret = read_file(fsp,outbuf+4,startpos,nread);
2092 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2101 _smb_setlen(outbuf,ret);
2102 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2106 /****************************************************************************
2107 Reply to a readbraw (core+ protocol).
2108 ****************************************************************************/
2110 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2112 ssize_t maxcount,mincount;
2115 char *header = outbuf;
2117 START_PROFILE(SMBreadbraw);
2119 if (srv_is_signing_active()) {
2120 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2124 * Special check if an oplock break has been issued
2125 * and the readraw request croses on the wire, we must
2126 * return a zero length response here.
2129 if(global_oplock_break) {
2130 _smb_setlen(header,0);
2131 if (write_data(smbd_server_fd(),header,4) != 4)
2133 DEBUG(5,("readbraw - oplock break finished\n"));
2134 END_PROFILE(SMBreadbraw);
2138 fsp = file_fsp(inbuf,smb_vwv0);
2140 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2142 * fsp could be NULL here so use the value from the packet. JRA.
2144 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2145 _smb_setlen(header,0);
2146 if (write_data(smbd_server_fd(),header,4) != 4)
2148 END_PROFILE(SMBreadbraw);
2152 CHECK_FSP(fsp,conn);
2154 flush_write_cache(fsp, READRAW_FLUSH);
2156 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2157 if(CVAL(inbuf,smb_wct) == 10) {
2159 * This is a large offset (64 bit) read.
2161 #ifdef LARGE_SMB_OFF_T
2163 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2165 #else /* !LARGE_SMB_OFF_T */
2168 * Ensure we haven't been sent a >32 bit offset.
2171 if(IVAL(inbuf,smb_vwv8) != 0) {
2172 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2173 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2174 _smb_setlen(header,0);
2175 if (write_data(smbd_server_fd(),header,4) != 4)
2177 END_PROFILE(SMBreadbraw);
2181 #endif /* LARGE_SMB_OFF_T */
2184 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2185 _smb_setlen(header,0);
2186 if (write_data(smbd_server_fd(),header,4) != 4)
2188 END_PROFILE(SMBreadbraw);
2192 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2193 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2195 /* ensure we don't overrun the packet size */
2196 maxcount = MIN(65535,maxcount);
2198 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2202 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) {
2206 if (startpos >= size) {
2209 nread = MIN(maxcount,(size - startpos));
2213 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2214 if (nread < mincount)
2218 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2219 (int)maxcount, (int)mincount, (int)nread ) );
2221 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2223 DEBUG(5,("readbraw finished\n"));
2224 END_PROFILE(SMBreadbraw);
2229 #define DBGC_CLASS DBGC_LOCKING
2231 /****************************************************************************
2232 Reply to a lockread (core+ protocol).
2233 ****************************************************************************/
2235 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2243 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2244 BOOL my_lock_ctx = False;
2245 START_PROFILE(SMBlockread);
2247 CHECK_FSP(fsp,conn);
2250 release_level_2_oplocks_on_change(fsp);
2252 numtoread = SVAL(inbuf,smb_vwv1);
2253 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2255 outsize = set_message(outbuf,5,3,True);
2256 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2257 data = smb_buf(outbuf) + 3;
2260 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2261 * protocol request that predates the read/write lock concept.
2262 * Thus instead of asking for a read lock here we need to ask
2263 * for a write lock. JRA.
2264 * Note that the requested lock size is unaffected by max_recv.
2267 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2268 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2270 if (NT_STATUS_V(status)) {
2273 * We used to make lockread a blocking lock. It turns out
2274 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2278 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2280 * A blocking lock was requested. Package up
2281 * this smb into a queued request and push it
2282 * onto the blocking lock queue.
2284 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2285 (SMB_BIG_UINT)numtoread)) {
2286 END_PROFILE(SMBlockread);
2291 END_PROFILE(SMBlockread);
2292 return ERROR_NT(status);
2296 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2299 if (numtoread > max_recv) {
2300 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2301 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2302 (unsigned int)numtoread, (unsigned int)max_recv ));
2303 numtoread = MIN(numtoread,max_recv);
2305 nread = read_file(fsp,data,startpos,numtoread);
2308 END_PROFILE(SMBlockread);
2309 return(UNIXERROR(ERRDOS,ERRnoaccess));
2313 SSVAL(outbuf,smb_vwv0,nread);
2314 SSVAL(outbuf,smb_vwv5,nread+3);
2315 SSVAL(smb_buf(outbuf),1,nread);
2317 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2318 fsp->fnum, (int)numtoread, (int)nread));
2320 END_PROFILE(SMBlockread);
2325 #define DBGC_CLASS DBGC_ALL
2327 /****************************************************************************
2329 ****************************************************************************/
2331 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2338 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2339 START_PROFILE(SMBread);
2341 CHECK_FSP(fsp,conn);
2344 numtoread = SVAL(inbuf,smb_vwv1);
2345 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2347 outsize = set_message(outbuf,5,3,True);
2348 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2350 * The requested read size cannot be greater than max_recv. JRA.
2352 if (numtoread > max_recv) {
2353 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2354 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2355 (unsigned int)numtoread, (unsigned int)max_recv ));
2356 numtoread = MIN(numtoread,max_recv);
2359 data = smb_buf(outbuf) + 3;
2361 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2362 END_PROFILE(SMBread);
2363 return ERROR_DOS(ERRDOS,ERRlock);
2367 nread = read_file(fsp,data,startpos,numtoread);
2370 END_PROFILE(SMBread);
2371 return(UNIXERROR(ERRDOS,ERRnoaccess));
2375 SSVAL(outbuf,smb_vwv0,nread);
2376 SSVAL(outbuf,smb_vwv5,nread+3);
2377 SCVAL(smb_buf(outbuf),0,1);
2378 SSVAL(smb_buf(outbuf),1,nread);
2380 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2381 fsp->fnum, (int)numtoread, (int)nread ) );
2383 END_PROFILE(SMBread);
2387 /****************************************************************************
2388 Reply to a read and X - possibly using sendfile.
2389 ****************************************************************************/
2391 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2392 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2396 char *data = smb_buf(outbuf);
2398 #if defined(WITH_SENDFILE)
2400 * We can only use sendfile on a non-chained packet
2401 * but we can use on a non-oplocked file. tridge proved this
2402 * on a train in Germany :-). JRA.
2405 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2406 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2407 SMB_STRUCT_STAT sbuf;
2410 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2411 return(UNIXERROR(ERRDOS,ERRnoaccess));
2413 if (startpos > sbuf.st_size)
2416 if (smb_maxcnt > (sbuf.st_size - startpos))
2417 smb_maxcnt = (sbuf.st_size - startpos);
2419 if (smb_maxcnt == 0)
2423 * Set up the packet header before send. We
2424 * assume here the sendfile will work (get the
2425 * correct amount of data).
2428 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2429 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2430 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2431 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2432 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2433 SCVAL(outbuf,smb_vwv0,0xFF);
2434 set_message(outbuf,12,smb_maxcnt,False);
2435 header.data = outbuf;
2436 header.length = data - outbuf;
2439 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2440 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2441 if (errno == ENOSYS) {
2446 * Special hack for broken Linux with no working sendfile. If we
2447 * return EINTR we sent the header but not the rest of the data.
2448 * Fake this up by doing read/write calls.
2451 if (errno == EINTR) {
2452 /* Ensure we don't do this again. */
2453 set_use_sendfile(SNUM(conn), False);
2454 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2456 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2457 len_outbuf - (data-outbuf))) == -1) {
2458 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2459 fsp->fsp_name, strerror(errno) ));
2460 exit_server("send_file_readX: fake_sendfile failed");
2462 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2463 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2464 /* Returning -1 here means successful sendfile. */
2468 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2469 fsp->fsp_name, strerror(errno) ));
2470 exit_server("send_file_readX sendfile failed");
2473 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2474 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2475 /* Returning -1 here means successful sendfile. */
2483 nread = read_file(fsp,data,startpos,smb_maxcnt);
2486 END_PROFILE(SMBreadX);
2487 return(UNIXERROR(ERRDOS,ERRnoaccess));
2490 outsize = set_message(outbuf,12,nread,False);
2491 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2492 SSVAL(outbuf,smb_vwv5,nread);
2493 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2494 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2495 SSVAL(smb_buf(outbuf),-2,nread);
2497 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2498 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2500 /* Returning the number of bytes we want to send back - including header. */
2504 /****************************************************************************
2505 Reply to a read and X.
2506 ****************************************************************************/
2508 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2510 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2511 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2513 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2515 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2518 START_PROFILE(SMBreadX);
2520 /* If it's an IPC, pass off the pipe handler. */
2522 END_PROFILE(SMBreadX);
2523 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2526 CHECK_FSP(fsp,conn);
2529 set_message(outbuf,12,0,True);
2531 if (global_client_caps & CAP_LARGE_READX) {
2532 if (SVAL(inbuf,smb_vwv7) == 1) {
2533 smb_maxcnt |= (1<<16);
2535 if (smb_maxcnt > BUFFER_SIZE) {
2536 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2537 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2538 END_PROFILE(SMBreadX);
2539 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2543 if(CVAL(inbuf,smb_wct) == 12) {
2544 #ifdef LARGE_SMB_OFF_T
2546 * This is a large offset (64 bit) read.
2548 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2550 #else /* !LARGE_SMB_OFF_T */
2553 * Ensure we haven't been sent a >32 bit offset.
2556 if(IVAL(inbuf,smb_vwv10) != 0) {
2557 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2558 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2559 END_PROFILE(SMBreadX);
2560 return ERROR_DOS(ERRDOS,ERRbadaccess);
2563 #endif /* LARGE_SMB_OFF_T */
2567 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2568 END_PROFILE(SMBreadX);
2569 return ERROR_DOS(ERRDOS,ERRlock);
2572 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2574 nread = chain_reply(inbuf,outbuf,length,bufsize);
2576 END_PROFILE(SMBreadX);
2580 /****************************************************************************
2581 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2582 ****************************************************************************/
2584 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2587 ssize_t total_written=0;
2588 size_t numtowrite=0;
2593 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2595 START_PROFILE(SMBwritebraw);
2597 if (srv_is_signing_active()) {
2598 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2601 CHECK_FSP(fsp,conn);
2604 tcount = IVAL(inbuf,smb_vwv1);
2605 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2606 write_through = BITSETW(inbuf+smb_vwv7,0);
2608 /* We have to deal with slightly different formats depending
2609 on whether we are using the core+ or lanman1.0 protocol */
2611 if(Protocol <= PROTOCOL_COREPLUS) {
2612 numtowrite = SVAL(smb_buf(inbuf),-2);
2613 data = smb_buf(inbuf);
2615 numtowrite = SVAL(inbuf,smb_vwv10);
2616 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2619 /* force the error type */
2620 SCVAL(inbuf,smb_com,SMBwritec);
2621 SCVAL(outbuf,smb_com,SMBwritec);
2623 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2624 END_PROFILE(SMBwritebraw);
2625 return(ERROR_DOS(ERRDOS,ERRlock));
2629 nwritten = write_file(fsp,data,startpos,numtowrite);
2631 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2632 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2634 if (nwritten < (ssize_t)numtowrite) {
2635 END_PROFILE(SMBwritebraw);
2636 return(UNIXERROR(ERRHRD,ERRdiskfull));
2639 total_written = nwritten;
2641 /* Return a message to the redirector to tell it to send more bytes */
2642 SCVAL(outbuf,smb_com,SMBwritebraw);
2643 SSVALS(outbuf,smb_vwv0,-1);
2644 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2645 if (!send_smb(smbd_server_fd(),outbuf))
2646 exit_server("reply_writebraw: send_smb failed.");
2648 /* Now read the raw data into the buffer and write it */
2649 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2650 exit_server("secondary writebraw failed");
2653 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2654 numtowrite = smb_len(inbuf);
2656 /* Set up outbuf to return the correct return */
2657 outsize = set_message(outbuf,1,0,True);
2658 SCVAL(outbuf,smb_com,SMBwritec);
2659 SSVAL(outbuf,smb_vwv0,total_written);
2661 if (numtowrite != 0) {
2663 if (numtowrite > BUFFER_SIZE) {
2664 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2665 (unsigned int)numtowrite ));
2666 exit_server("secondary writebraw failed");
2669 if (tcount > nwritten+numtowrite) {
2670 DEBUG(3,("Client overestimated the write %d %d %d\n",
2671 (int)tcount,(int)nwritten,(int)numtowrite));
2674 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2675 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2677 exit_server("secondary writebraw failed");
2680 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2682 if (nwritten < (ssize_t)numtowrite) {
2683 SCVAL(outbuf,smb_rcls,ERRHRD);
2684 SSVAL(outbuf,smb_err,ERRdiskfull);
2688 total_written += nwritten;
2691 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2692 sync_file(conn,fsp);
2694 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2695 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2697 /* we won't return a status if write through is not selected - this follows what WfWg does */
2698 END_PROFILE(SMBwritebraw);
2699 if (!write_through && total_written==tcount) {
2701 #if RABBIT_PELLET_FIX
2703 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2704 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2706 if (!send_keepalive(smbd_server_fd()))
2707 exit_server("reply_writebraw: send of keepalive failed");
2716 #define DBGC_CLASS DBGC_LOCKING
2718 /****************************************************************************
2719 Reply to a writeunlock (core+).
2720 ****************************************************************************/
2722 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2723 int size, int dum_buffsize)
2725 ssize_t nwritten = -1;
2729 NTSTATUS status = NT_STATUS_OK;
2730 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2732 START_PROFILE(SMBwriteunlock);
2734 CHECK_FSP(fsp,conn);
2737 numtowrite = SVAL(inbuf,smb_vwv1);
2738 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2739 data = smb_buf(inbuf) + 3;
2741 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2742 END_PROFILE(SMBwriteunlock);
2743 return ERROR_DOS(ERRDOS,ERRlock);
2746 /* The special X/Open SMB protocol handling of
2747 zero length writes is *NOT* done for
2752 nwritten = write_file(fsp,data,startpos,numtowrite);
2754 if (lp_syncalways(SNUM(conn)))
2755 sync_file(conn,fsp);
2757 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2758 END_PROFILE(SMBwriteunlock);
2759 return(UNIXERROR(ERRHRD,ERRdiskfull));
2763 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2764 (SMB_BIG_UINT)startpos);
2765 if (NT_STATUS_V(status)) {
2766 END_PROFILE(SMBwriteunlock);
2767 return ERROR_NT(status);
2771 outsize = set_message(outbuf,1,0,True);
2773 SSVAL(outbuf,smb_vwv0,nwritten);
2775 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2776 fsp->fnum, (int)numtowrite, (int)nwritten));
2778 END_PROFILE(SMBwriteunlock);
2783 #define DBGC_CLASS DBGC_ALL
2785 /****************************************************************************
2787 ****************************************************************************/
2789 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2792 ssize_t nwritten = -1;
2795 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2797 START_PROFILE(SMBwrite);
2799 /* If it's an IPC, pass off the pipe handler. */
2801 END_PROFILE(SMBwrite);
2802 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2805 CHECK_FSP(fsp,conn);
2808 numtowrite = SVAL(inbuf,smb_vwv1);
2809 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2810 data = smb_buf(inbuf) + 3;
2812 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2813 END_PROFILE(SMBwrite);
2814 return ERROR_DOS(ERRDOS,ERRlock);
2818 * X/Open SMB protocol says that if smb_vwv1 is
2819 * zero then the file size should be extended or
2820 * truncated to the size given in smb_vwv[2-3].
2823 if(numtowrite == 0) {
2825 * This is actually an allocate call, and set EOF. JRA.
2827 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2829 END_PROFILE(SMBwrite);
2830 return ERROR_NT(NT_STATUS_DISK_FULL);
2832 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2834 END_PROFILE(SMBwrite);
2835 return ERROR_NT(NT_STATUS_DISK_FULL);
2838 nwritten = write_file(fsp,data,startpos,numtowrite);
2840 if (lp_syncalways(SNUM(conn)))
2841 sync_file(conn,fsp);
2843 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2844 END_PROFILE(SMBwrite);
2845 return(UNIXERROR(ERRHRD,ERRdiskfull));
2848 outsize = set_message(outbuf,1,0,True);
2850 SSVAL(outbuf,smb_vwv0,nwritten);
2852 if (nwritten < (ssize_t)numtowrite) {
2853 SCVAL(outbuf,smb_rcls,ERRHRD);
2854 SSVAL(outbuf,smb_err,ERRdiskfull);
2857 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2859 END_PROFILE(SMBwrite);
2863 /****************************************************************************
2864 Reply to a write and X.
2865 ****************************************************************************/
2867 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2869 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2870 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2871 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2872 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2873 ssize_t nwritten = -1;
2874 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2875 unsigned int smblen = smb_len(inbuf);
2877 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2878 START_PROFILE(SMBwriteX);
2880 /* If it's an IPC, pass off the pipe handler. */
2882 END_PROFILE(SMBwriteX);
2883 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2886 CHECK_FSP(fsp,conn);
2889 /* Deal with possible LARGE_WRITEX */
2891 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2893 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2894 END_PROFILE(SMBwriteX);
2895 return ERROR_DOS(ERRDOS,ERRbadmem);
2898 data = smb_base(inbuf) + smb_doff;
2900 if(CVAL(inbuf,smb_wct) == 14) {
2901 #ifdef LARGE_SMB_OFF_T
2903 * This is a large offset (64 bit) write.
2905 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2907 #else /* !LARGE_SMB_OFF_T */
2910 * Ensure we haven't been sent a >32 bit offset.
2913 if(IVAL(inbuf,smb_vwv12) != 0) {
2914 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2915 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2916 END_PROFILE(SMBwriteX);
2917 return ERROR_DOS(ERRDOS,ERRbadaccess);
2920 #endif /* LARGE_SMB_OFF_T */
2923 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2924 END_PROFILE(SMBwriteX);
2925 return ERROR_DOS(ERRDOS,ERRlock);
2928 /* X/Open SMB protocol says that, unlike SMBwrite
2929 if the length is zero then NO truncation is
2930 done, just a write of zero. To truncate a file,
2936 nwritten = write_file(fsp,data,startpos,numtowrite);
2938 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2939 END_PROFILE(SMBwriteX);
2940 return(UNIXERROR(ERRHRD,ERRdiskfull));
2943 set_message(outbuf,6,0,True);
2945 SSVAL(outbuf,smb_vwv2,nwritten);
2947 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2949 if (nwritten < (ssize_t)numtowrite) {
2950 SCVAL(outbuf,smb_rcls,ERRHRD);
2951 SSVAL(outbuf,smb_err,ERRdiskfull);
2954 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2955 fsp->fnum, (int)numtowrite, (int)nwritten));
2957 if (lp_syncalways(SNUM(conn)) || write_through)
2958 sync_file(conn,fsp);
2960 END_PROFILE(SMBwriteX);
2961 return chain_reply(inbuf,outbuf,length,bufsize);
2964 /****************************************************************************
2966 ****************************************************************************/
2968 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2974 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2975 START_PROFILE(SMBlseek);
2977 CHECK_FSP(fsp,conn);
2979 flush_write_cache(fsp, SEEK_FLUSH);
2981 mode = SVAL(inbuf,smb_vwv1) & 3;
2982 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2983 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2992 res = fsp->pos + startpos;
3003 if (umode == SEEK_END) {
3004 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
3005 if(errno == EINVAL) {
3006 SMB_OFF_T current_pos = startpos;
3007 SMB_STRUCT_STAT sbuf;
3009 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
3010 END_PROFILE(SMBlseek);
3011 return(UNIXERROR(ERRDOS,ERRnoaccess));
3014 current_pos += sbuf.st_size;
3016 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
3021 END_PROFILE(SMBlseek);
3022 return(UNIXERROR(ERRDOS,ERRnoaccess));
3028 outsize = set_message(outbuf,2,0,True);
3029 SIVAL(outbuf,smb_vwv0,res);
3031 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3032 fsp->fnum, (double)startpos, (double)res, mode));
3034 END_PROFILE(SMBlseek);
3038 /****************************************************************************
3040 ****************************************************************************/
3042 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3044 int outsize = set_message(outbuf,0,0,True);
3045 uint16 fnum = SVAL(inbuf,smb_vwv0);
3046 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3047 START_PROFILE(SMBflush);
3050 CHECK_FSP(fsp,conn);
3053 file_sync_all(conn);
3055 sync_file(conn,fsp);
3058 DEBUG(3,("flush\n"));
3059 END_PROFILE(SMBflush);
3063 /****************************************************************************
3065 ****************************************************************************/
3067 int reply_exit(connection_struct *conn,
3068 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3071 START_PROFILE(SMBexit);
3073 file_close_pid(SVAL(inbuf,smb_pid));
3075 outsize = set_message(outbuf,0,0,True);
3077 DEBUG(3,("exit\n"));
3079 END_PROFILE(SMBexit);
3083 /****************************************************************************
3084 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3085 ****************************************************************************/
3087 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3092 int32 eclass = 0, err = 0;
3093 files_struct *fsp = NULL;
3094 START_PROFILE(SMBclose);
3096 outsize = set_message(outbuf,0,0,True);
3098 /* If it's an IPC, pass off to the pipe handler. */
3100 END_PROFILE(SMBclose);
3101 return reply_pipe_close(conn, inbuf,outbuf);
3104 fsp = file_fsp(inbuf,smb_vwv0);
3107 * We can only use CHECK_FSP if we know it's not a directory.
3110 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3111 END_PROFILE(SMBclose);
3112 return ERROR_DOS(ERRDOS,ERRbadfid);
3115 if(fsp->is_directory) {
3117 * Special case - close NT SMB directory handle.
3119 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3120 close_file(fsp,True);
3123 * Close ordinary file.
3128 /* Save the name for time set in close. */
3129 pstrcpy( file_name, fsp->fsp_name);
3131 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3133 conn->num_files_open));
3136 * Take care of any time sent in the close.
3139 mtime = make_unix_date3(inbuf+smb_vwv1);
3140 fsp_set_pending_modtime(fsp, mtime);
3143 * close_file() returns the unix errno if an error
3144 * was detected on close - normally this is due to
3145 * a disk full error. If not then it was probably an I/O error.
3148 if((close_err = close_file(fsp,True)) != 0) {
3150 END_PROFILE(SMBclose);
3151 return (UNIXERROR(ERRHRD,ERRgeneral));
3155 /* We have a cached error */
3157 END_PROFILE(SMBclose);
3158 return ERROR_DOS(eclass,err);
3161 END_PROFILE(SMBclose);
3165 /****************************************************************************
3166 Reply to a writeclose (Core+ protocol).
3167 ****************************************************************************/
3169 int reply_writeclose(connection_struct *conn,
3170 char *inbuf,char *outbuf, int size, int dum_buffsize)
3173 ssize_t nwritten = -1;
3179 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3180 START_PROFILE(SMBwriteclose);
3182 CHECK_FSP(fsp,conn);
3185 numtowrite = SVAL(inbuf,smb_vwv1);
3186 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3187 mtime = make_unix_date3(inbuf+smb_vwv4);
3188 data = smb_buf(inbuf) + 1;
3190 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3191 END_PROFILE(SMBwriteclose);
3192 return ERROR_DOS(ERRDOS,ERRlock);
3195 nwritten = write_file(fsp,data,startpos,numtowrite);
3197 set_filetime(conn, fsp->fsp_name,mtime);
3200 * More insanity. W2K only closes the file if writelen > 0.
3205 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3207 close_err = close_file(fsp,True);
3210 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3211 fsp->fnum, (int)numtowrite, (int)nwritten,
3212 conn->num_files_open));
3214 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3215 END_PROFILE(SMBwriteclose);
3216 return(UNIXERROR(ERRHRD,ERRdiskfull));
3219 if(close_err != 0) {
3221 END_PROFILE(SMBwriteclose);
3222 return(UNIXERROR(ERRHRD,ERRgeneral));
3225 outsize = set_message(outbuf,1,0,True);
3227 SSVAL(outbuf,smb_vwv0,nwritten);
3228 END_PROFILE(SMBwriteclose);
3233 #define DBGC_CLASS DBGC_LOCKING
3235 /****************************************************************************
3237 ****************************************************************************/
3239 int reply_lock(connection_struct *conn,
3240 char *inbuf,char *outbuf, int length, int dum_buffsize)
3242 int outsize = set_message(outbuf,0,0,True);
3243 SMB_BIG_UINT count,offset;
3245 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3246 BOOL my_lock_ctx = False;
3248 START_PROFILE(SMBlock);
3250 CHECK_FSP(fsp,conn);
3252 release_level_2_oplocks_on_change(fsp);
3254 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3255 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3257 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3258 fsp->fd, fsp->fnum, (double)offset, (double)count));
3260 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3261 if (NT_STATUS_V(status)) {
3263 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3264 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3266 * A blocking lock was requested. Package up
3267 * this smb into a queued request and push it
3268 * onto the blocking lock queue.
3270 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3271 END_PROFILE(SMBlock);
3276 END_PROFILE(SMBlock);
3277 return ERROR_NT(status);
3280 END_PROFILE(SMBlock);
3284 /****************************************************************************
3286 ****************************************************************************/
3288 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3291 int outsize = set_message(outbuf,0,0,True);
3292 SMB_BIG_UINT count,offset;
3294 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3295 START_PROFILE(SMBunlock);
3297 CHECK_FSP(fsp,conn);
3299 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3300 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3302 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3303 if (NT_STATUS_V(status)) {
3304 END_PROFILE(SMBunlock);
3305 return ERROR_NT(status);
3308 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3309 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3311 END_PROFILE(SMBunlock);
3316 #define DBGC_CLASS DBGC_ALL
3318 /****************************************************************************
3320 ****************************************************************************/
3322 int reply_tdis(connection_struct *conn,
3323 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3325 int outsize = set_message(outbuf,0,0,True);
3327 START_PROFILE(SMBtdis);
3329 vuid = SVAL(inbuf,smb_uid);
3332 DEBUG(4,("Invalid connection in tdis\n"));
3333 END_PROFILE(SMBtdis);
3334 return ERROR_DOS(ERRSRV,ERRinvnid);
3339 close_cnum(conn,vuid);
3341 END_PROFILE(SMBtdis);
3345 /****************************************************************************
3347 ****************************************************************************/
3349 int reply_echo(connection_struct *conn,
3350 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3352 int smb_reverb = SVAL(inbuf,smb_vwv0);
3354 unsigned int data_len = smb_buflen(inbuf);
3355 int outsize = set_message(outbuf,1,data_len,True);
3356 START_PROFILE(SMBecho);
3358 if (data_len > BUFFER_SIZE) {
3359 DEBUG(0,("reply_echo: data_len too large.\n"));
3360 END_PROFILE(SMBecho);
3364 /* copy any incoming data back out */
3366 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3368 if (smb_reverb > 100) {
3369 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3373 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3374 SSVAL(outbuf,smb_vwv0,seq_num);
3376 smb_setlen(outbuf,outsize - 4);
3378 if (!send_smb(smbd_server_fd(),outbuf))
3379 exit_server("reply_echo: send_smb failed.");
3382 DEBUG(3,("echo %d times\n", smb_reverb));
3386 END_PROFILE(SMBecho);
3390 /****************************************************************************
3391 Reply to a printopen.
3392 ****************************************************************************/
3394 int reply_printopen(connection_struct *conn,
3395 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3399 START_PROFILE(SMBsplopen);
3401 if (!CAN_PRINT(conn)) {
3402 END_PROFILE(SMBsplopen);
3403 return ERROR_DOS(ERRDOS,ERRnoaccess);
3406 /* Open for exclusive use, write only. */
3407 fsp = print_fsp_open(conn, NULL);
3410 END_PROFILE(SMBsplopen);
3411 return(UNIXERROR(ERRDOS,ERRnoaccess));
3414 outsize = set_message(outbuf,1,0,True);
3415 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3417 DEBUG(3,("openprint fd=%d fnum=%d\n",
3418 fsp->fd, fsp->fnum));
3420 END_PROFILE(SMBsplopen);
3424 /****************************************************************************
3425 Reply to a printclose.
3426 ****************************************************************************/
3428 int reply_printclose(connection_struct *conn,
3429 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3431 int outsize = set_message(outbuf,0,0,True);
3432 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3434 START_PROFILE(SMBsplclose);
3436 CHECK_FSP(fsp,conn);
3438 if (!CAN_PRINT(conn)) {
3439 END_PROFILE(SMBsplclose);
3440 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3443 DEBUG(3,("printclose fd=%d fnum=%d\n",
3444 fsp->fd,fsp->fnum));
3446 close_err = close_file(fsp,True);
3448 if(close_err != 0) {
3450 END_PROFILE(SMBsplclose);
3451 return(UNIXERROR(ERRHRD,ERRgeneral));
3454 END_PROFILE(SMBsplclose);
3458 /****************************************************************************
3459 Reply to a printqueue.
3460 ****************************************************************************/
3462 int reply_printqueue(connection_struct *conn,
3463 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3465 int outsize = set_message(outbuf,2,3,True);
3466 int max_count = SVAL(inbuf,smb_vwv0);
3467 int start_index = SVAL(inbuf,smb_vwv1);
3468 START_PROFILE(SMBsplretq);
3470 /* we used to allow the client to get the cnum wrong, but that
3471 is really quite gross and only worked when there was only
3472 one printer - I think we should now only accept it if they
3473 get it right (tridge) */
3474 if (!CAN_PRINT(conn)) {
3475 END_PROFILE(SMBsplretq);
3476 return ERROR_DOS(ERRDOS,ERRnoaccess);
3479 SSVAL(outbuf,smb_vwv0,0);
3480 SSVAL(outbuf,smb_vwv1,0);
3481 SCVAL(smb_buf(outbuf),0,1);
3482 SSVAL(smb_buf(outbuf),1,0);
3484 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3485 start_index, max_count));
3488 print_queue_struct *queue = NULL;
3489 print_status_struct status;
3490 char *p = smb_buf(outbuf) + 3;
3491 int count = print_queue_status(SNUM(conn), &queue, &status);
3492 int num_to_get = ABS(max_count);
3493 int first = (max_count>0?start_index:start_index+max_count+1);
3499 num_to_get = MIN(num_to_get,count-first);
3502 for (i=first;i<first+num_to_get;i++) {
3503 put_dos_date2(p,0,queue[i].time);
3504 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3505 SSVAL(p,5, queue[i].job);
3506 SIVAL(p,7,queue[i].size);
3508 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3513 outsize = set_message(outbuf,2,28*count+3,False);
3514 SSVAL(outbuf,smb_vwv0,count);
3515 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3516 SCVAL(smb_buf(outbuf),0,1);
3517 SSVAL(smb_buf(outbuf),1,28*count);
3522 DEBUG(3,("%d entries returned in queue\n",count));
3525 END_PROFILE(SMBsplretq);
3529 /****************************************************************************
3530 Reply to a printwrite.
3531 ****************************************************************************/
3533 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3536 int outsize = set_message(outbuf,0,0,True);
3538 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3540 START_PROFILE(SMBsplwr);
3542 if (!CAN_PRINT(conn)) {
3543 END_PROFILE(SMBsplwr);
3544 return ERROR_DOS(ERRDOS,ERRnoaccess);
3547 CHECK_FSP(fsp,conn);
3550 numtowrite = SVAL(smb_buf(inbuf),1);
3551 data = smb_buf(inbuf) + 3;
3553 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3554 END_PROFILE(SMBsplwr);
3555 return(UNIXERROR(ERRHRD,ERRdiskfull));
3558 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3560 END_PROFILE(SMBsplwr);
3564 /****************************************************************************
3565 The guts of the mkdir command, split out so it may be called by the NT SMB
3567 ****************************************************************************/
3569 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3573 if(!CAN_WRITE(conn)) {
3574 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3576 return map_nt_error_from_unix(errno);
3580 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3583 if (!check_name(directory, conn)) {
3584 if(errno == ENOENT) {
3586 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3588 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3591 return map_nt_error_from_unix(errno);
3594 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3596 if(errno == ENOENT) {
3597 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3599 return map_nt_error_from_unix(errno);
3602 return NT_STATUS_OK;
3605 /****************************************************************************
3607 ****************************************************************************/
3609 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3614 BOOL bad_path = False;
3615 SMB_STRUCT_STAT sbuf;
3617 START_PROFILE(SMBmkdir);
3619 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3620 if (!NT_STATUS_IS_OK(status)) {
3621 END_PROFILE(SMBmkdir);
3622 return ERROR_NT(status);
3625 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3627 unix_convert(directory,conn,0,&bad_path,&sbuf);
3629 if( is_ntfs_stream_name(directory)) {
3630 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3631 END_PROFILE(SMBmkdir);
3632 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3635 status = mkdir_internal(conn, directory,bad_path);
3636 if (!NT_STATUS_IS_OK(status)) {
3637 END_PROFILE(SMBmkdir);
3638 return ERROR_NT(status);
3641 if (lp_inherit_owner(SNUM(conn))) {
3642 /* Ensure we're checking for a symlink here.... */
3643 /* We don't want to get caught by a symlink racer. */
3645 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3646 END_PROFILE(SMBmkdir);
3647 return(UNIXERROR(ERRDOS,ERRnoaccess));
3650 if(!S_ISDIR(sbuf.st_mode)) {
3651 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3652 END_PROFILE(SMBmkdir);
3653 return(UNIXERROR(ERRDOS,ERRnoaccess));
3656 change_owner_to_parent(conn, NULL, directory, &sbuf);
3659 outsize = set_message(outbuf,0,0,True);
3661 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3663 END_PROFILE(SMBmkdir);
3667 /****************************************************************************
3668 Static function used by reply_rmdir to delete an entire directory
3669 tree recursively. Return False on ok, True on fail.
3670 ****************************************************************************/
3672 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3674 const char *dname = NULL;
3677 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3682 while((dname = ReadDirName(dir_hnd, &offset))) {
3686 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3689 if (!is_visible_file(conn, directory, dname, &st, False))
3692 /* Construct the full name. */
3693 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3699 pstrcpy(fullname, directory);
3700 pstrcat(fullname, "/");
3701 pstrcat(fullname, dname);
3703 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3708 if(st.st_mode & S_IFDIR) {
3709 if(recursive_rmdir(conn, fullname)!=0) {
3713 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3717 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3726 /****************************************************************************
3727 The internals of the rmdir code - called elsewhere.
3728 ****************************************************************************/
3730 BOOL rmdir_internals(connection_struct *conn, char *directory)
3735 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3736 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3738 * Check to see if the only thing in this directory are
3739 * vetoed files/directories. If so then delete them and
3740 * retry. If we fail to delete any of them (and we *don't*
3741 * do a recursive delete) then fail the rmdir.
3743 BOOL all_veto_files = True;
3745 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3747 if(dir_hnd != NULL) {
3748 long dirpos = TellDir(dir_hnd);
3749 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3750 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3752 if (!is_visible_file(conn, directory, dname, &st, False))
3754 if(!IS_VETO_PATH(conn, dname)) {
3755 all_veto_files = False;
3760 if(all_veto_files) {
3761 SeekDir(dir_hnd,dirpos);
3762 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3765 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3767 if (!is_visible_file(conn, directory, dname, &st, False))
3770 /* Construct the full name. */
3771 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3776 pstrcpy(fullname, directory);
3777 pstrcat(fullname, "/");
3778 pstrcat(fullname, dname);
3780 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3782 if(st.st_mode & S_IFDIR) {
3783 if(lp_recursive_veto_delete(SNUM(conn))) {
3784 if(recursive_rmdir(conn, fullname) != 0)
3787 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3789 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3793 /* Retry the rmdir */
3794 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3804 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3809 /****************************************************************************
3811 ****************************************************************************/
3813 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3818 BOOL bad_path = False;
3819 SMB_STRUCT_STAT sbuf;
3821 START_PROFILE(SMBrmdir);
3823 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3824 if (!NT_STATUS_IS_OK(status)) {
3825 END_PROFILE(SMBrmdir);
3826 return ERROR_NT(status);
3829 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3831 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3833 END_PROFILE(SMBrmdir);
3834 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3837 if (check_name(directory,conn)) {
3838 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3839 ok = rmdir_internals(conn, directory);
3843 END_PROFILE(SMBrmdir);
3844 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3847 outsize = set_message(outbuf,0,0,True);
3849 DEBUG( 3, ( "rmdir %s\n", directory ) );
3851 END_PROFILE(SMBrmdir);
3855 /*******************************************************************
3856 Resolve wildcards in a filename rename.
3857 Note that name is in UNIX charset and thus potentially can be more
3858 than fstring buffer (255 bytes) especially in default UTF-8 case.
3859 Therefore, we use pstring inside and all calls should ensure that
3860 name2 is at least pstring-long (they do already)
3861 ********************************************************************/
3863 static BOOL resolve_wildcards(const char *name1, char *name2)
3865 pstring root1,root2;
3867 char *p,*p2, *pname1, *pname2;
3868 int available_space, actual_space;
3871 pname1 = strrchr_m(name1,'/');
3872 pname2 = strrchr_m(name2,'/');
3874 if (!pname1 || !pname2)
3877 pstrcpy(root1,pname1);
3878 pstrcpy(root2,pname2);
3879 p = strrchr_m(root1,'.');
3886 p = strrchr_m(root2,'.');
3900 } else if (*p2 == '*') {
3916 } else if (*p2 == '*') {
3926 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3929 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3930 if (actual_space >= available_space - 1) {
3931 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3932 actual_space - available_space));
3935 pstrcpy_base(pname2, root2, name2);
3941 /****************************************************************************
3942 Ensure open files have their names updates.
3943 ****************************************************************************/
3945 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3948 BOOL did_rename = False;
3950 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3951 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3952 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3953 fsp->fsp_name, newname ));
3954 string_set(&fsp->fsp_name, newname);
3959 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3960 (unsigned int)dev, (double)inode, newname ));
3963 /****************************************************************************
3964 Rename an open file - given an fsp.
3965 ****************************************************************************/
3967 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3969 SMB_STRUCT_STAT sbuf;
3970 BOOL bad_path = False;
3971 pstring newname_last_component;
3972 NTSTATUS error = NT_STATUS_OK;
3977 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3979 /* Quick check for "." and ".." */
3980 if (!bad_path && newname_last_component[0] == '.') {
3981 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3982 return NT_STATUS_ACCESS_DENIED;
3985 if (!rcdest && bad_path) {
3986 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3989 /* Ensure newname contains a '/' */
3990 if(strrchr_m(newname,'/') == 0) {
3993 pstrcpy(tmpstr, "./");
3994 pstrcat(tmpstr, newname);
3995 pstrcpy(newname, tmpstr);
3999 * Check for special case with case preserving and not
4000 * case sensitive. If the old last component differs from the original
4001 * last component only by case, then we should allow
4002 * the rename (user is trying to change the case of the
4006 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4007 strequal(newname, fsp->fsp_name)) {
4009 pstring newname_modified_last_component;
4012 * Get the last component of the modified name.
4013 * Note that we guarantee that newname contains a '/'
4016 p = strrchr_m(newname,'/');
4017 pstrcpy(newname_modified_last_component,p+1);
4019 if(strcsequal(newname_modified_last_component,
4020 newname_last_component) == False) {
4022 * Replace the modified last component with
4025 pstrcpy(p+1, newname_last_component);
4030 * If the src and dest names are identical - including case,
4031 * don't do the rename, just return success.
4034 if (strcsequal(fsp->fsp_name, newname)) {
4035 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4037 return NT_STATUS_OK;
4040 dest_exists = vfs_object_exist(conn,newname,NULL);
4042 if(!replace_if_exists && dest_exists) {
4043 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4044 fsp->fsp_name,newname));
4045 return NT_STATUS_OBJECT_NAME_COLLISION;
4048 error = can_rename(conn,newname,attrs,&sbuf);
4050 if (dest_exists && !NT_STATUS_IS_OK(error)) {
4051 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4052 nt_errstr(error), fsp->fsp_name,newname));
4053 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4054 error = NT_STATUS_ACCESS_DENIED;
4058 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4059 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4060 fsp->fsp_name,newname));
4061 rename_open_files(conn, fsp->dev, fsp->inode, newname);
4062 return NT_STATUS_OK;
4065 if (errno == ENOTDIR || errno == EISDIR)
4066 error = NT_STATUS_OBJECT_NAME_COLLISION;
4068 error = map_nt_error_from_unix(errno);
4070 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4071 nt_errstr(error), fsp->fsp_name,newname));
4076 /****************************************************************************
4077 The guts of the rename command, split out so it may be called by the NT SMB
4079 ****************************************************************************/
4081 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
4085 pstring last_component_src;
4086 pstring last_component_dest;
4089 BOOL bad_path_src = False;
4090 BOOL bad_path_dest = False;
4092 NTSTATUS error = NT_STATUS_OK;
4095 SMB_STRUCT_STAT sbuf1, sbuf2;
4097 *directory = *mask = 0;
4102 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4103 if (!rc && bad_path_src) {
4104 if (ms_has_wild(last_component_src))
4105 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4106 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4109 /* Quick check for "." and ".." */
4110 if (last_component_src[0] == '.') {
4111 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4112 return NT_STATUS_OBJECT_NAME_INVALID;
4116 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4118 /* Quick check for "." and ".." */
4119 if (last_component_dest[0] == '.') {
4120 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4121 return NT_STATUS_OBJECT_NAME_INVALID;
4126 * Split the old name into directory and last component
4127 * strings. Note that unix_convert may have stripped off a
4128 * leading ./ from both name and newname if the rename is
4129 * at the root of the share. We need to make sure either both
4130 * name and newname contain a / character or neither of them do
4131 * as this is checked in resolve_wildcards().
4134 p = strrchr_m(name,'/');
4136 pstrcpy(directory,".");
4140 pstrcpy(directory,name);
4142 *p = '/'; /* Replace needed for exceptional test below. */
4146 * We should only check the mangled cache
4147 * here if unix_convert failed. This means
4148 * that the path in 'mask' doesn't exist
4149 * on the file system and so we need to look
4150 * for a possible mangle. This patch from
4151 * Tine Smukavec <valentin.smukavec@hermes.si>.
4154 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4155 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4157 has_wild = ms_has_wild(mask);
4161 * No wildcards - just process the one file.
4163 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4165 /* Add a terminating '/' to the directory name. */
4166 pstrcat(directory,"/");
4167 pstrcat(directory,mask);
4169 /* Ensure newname contains a '/' also */
4170 if(strrchr_m(newname,'/') == 0) {
4173 pstrcpy(tmpstr, "./");
4174 pstrcat(tmpstr, newname);
4175 pstrcpy(newname, tmpstr);
4178 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4179 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4180 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4181 newname, last_component_dest, is_short_name));
4184 * Check for special case with case preserving and not
4185 * case sensitive, if directory and newname are identical,
4186 * and the old last component differs from the original
4187 * last component only by case, then we should allow
4188 * the rename (user is trying to change the case of the
4191 if((conn->case_sensitive == False) &&
4192 (((conn->case_preserve == True) &&
4193 (is_short_name == False)) ||
4194 ((conn->short_case_preserve == True) &&
4195 (is_short_name == True))) &&
4196 strcsequal(directory, newname)) {
4197 pstring modified_last_component;
4200 * Get the last component of the modified name.
4201 * Note that we guarantee that newname contains a '/'
4204 p = strrchr_m(newname,'/');
4205 pstrcpy(modified_last_component,p+1);
4207 if(strcsequal(modified_last_component,
4208 last_component_dest) == False) {
4210 * Replace the modified last component with
4213 pstrcpy(p+1, last_component_dest);
4217 resolve_wildcards(directory,newname);
4220 * The source object must exist.
4223 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4224 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4225 directory,newname));
4227 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4229 * Must return different errors depending on whether the parent
4230 * directory existed or not.
4233 p = strrchr_m(directory, '/');
4235 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4237 if (vfs_object_exist(conn, directory, NULL))
4238 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4239 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4241 error = map_nt_error_from_unix(errno);
4242 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4243 nt_errstr(error), directory,newname));
4248 if (!rcdest && bad_path_dest) {
4249 if (ms_has_wild(last_component_dest))
4250 return NT_STATUS_OBJECT_NAME_INVALID;
4251 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4254 error = can_rename(conn,directory,attrs,&sbuf1);
4256 if (!NT_STATUS_IS_OK(error)) {
4257 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4258 nt_errstr(error), directory,newname));
4263 * If the src and dest names are identical - including case,
4264 * don't do the rename, just return success.
4267 if (strcsequal(directory, newname)) {
4268 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4269 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4270 return NT_STATUS_OK;
4273 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4274 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4275 directory,newname));
4276 return NT_STATUS_OBJECT_NAME_COLLISION;
4279 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4280 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4281 directory,newname));
4282 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4283 return NT_STATUS_OK;
4286 if (errno == ENOTDIR || errno == EISDIR)
4287 error = NT_STATUS_OBJECT_NAME_COLLISION;
4289 error = map_nt_error_from_unix(errno);
4291 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4292 nt_errstr(error), directory,newname));
4297 * Wildcards - process each file that matches.
4299 struct smb_Dir *dir_hnd = NULL;
4303 if (check_name(directory,conn))
4304 dir_hnd = OpenDir(conn, directory);
4308 error = NT_STATUS_NO_SUCH_FILE;
4309 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4311 if (strequal(mask,"????????.???"))
4314 while ((dname = ReadDirName(dir_hnd, &offset))) {
4316 BOOL sysdir_entry = False;
4318 pstrcpy(fname,dname);
4320 /* Quick check for "." and ".." */
4321 if (fname[0] == '.') {
4322 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4324 sysdir_entry = True;
4331 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4334 if(!mask_match(fname, mask, conn->case_sensitive))
4338 error = NT_STATUS_OBJECT_NAME_INVALID;
4342 error = NT_STATUS_ACCESS_DENIED;
4343 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4344 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4345 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4346 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4349 error = can_rename(conn,fname,attrs,&sbuf1);
4350 if (!NT_STATUS_IS_OK(error)) {
4351 DEBUG(6,("rename %s refused\n", fname));
4354 pstrcpy(destname,newname);
4356 if (!resolve_wildcards(fname,destname)) {
4357 DEBUG(6,("resolve_wildcards %s %s failed\n",
4362 if (strcsequal(fname,destname)) {
4363 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4364 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4366 error = NT_STATUS_OK;
4370 if (!replace_if_exists &&
4371 vfs_file_exist(conn,destname, NULL)) {
4372 DEBUG(6,("file_exist %s\n", destname));
4373 error = NT_STATUS_OBJECT_NAME_COLLISION;
4377 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4378 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4380 error = NT_STATUS_OK;
4382 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4387 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4388 if (!rcdest && bad_path_dest) {
4389 if (ms_has_wild(last_component_dest))
4390 return NT_STATUS_OBJECT_NAME_INVALID;
4391 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4396 if (count == 0 && NT_STATUS_IS_OK(error)) {
4397 error = map_nt_error_from_unix(errno);
4403 /****************************************************************************
4405 ****************************************************************************/
4407 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4414 uint16 attrs = SVAL(inbuf,smb_vwv0);
4417 START_PROFILE(SMBmv);
4419 p = smb_buf(inbuf) + 1;
4420 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4421 if (!NT_STATUS_IS_OK(status)) {
4423 return ERROR_NT(status);
4426 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4427 if (!NT_STATUS_IS_OK(status)) {
4429 return ERROR_NT(status);
4432 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4433 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4435 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4437 status = rename_internals(conn, name, newname, attrs, False);
4438 if (!NT_STATUS_IS_OK(status)) {
4440 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4441 /* We have re-scheduled this call. */
4444 return ERROR_NT(status);
4448 * Win2k needs a changenotify request response before it will
4449 * update after a rename..
4451 process_pending_change_notify_queue((time_t)0);
4452 outsize = set_message(outbuf,0,0,True);
4458 /*******************************************************************
4459 Copy a file as part of a reply_copy.
4460 ******************************************************************/
4462 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4463 int count,BOOL target_is_directory, int *err_ret)
4466 SMB_STRUCT_STAT src_sbuf, sbuf2;
4468 files_struct *fsp1,*fsp2;
4474 pstrcpy(dest,dest1);
4475 if (target_is_directory) {
4476 char *p = strrchr_m(src,'/');
4485 if (!vfs_file_exist(conn,src,&src_sbuf))
4488 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4489 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4495 if (!target_is_directory && count)
4496 ofun = FILE_EXISTS_OPEN;
4498 dosattrs = dos_mode(conn, src, &src_sbuf);
4499 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4500 ZERO_STRUCTP(&sbuf2);
4502 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4503 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4506 close_file(fsp1,False);
4510 if ((ofun&3) == 1) {
4511 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4512 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4514 * Stop the copy from occurring.
4517 src_sbuf.st_size = 0;
4521 if (src_sbuf.st_size)
4522 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4524 close_file(fsp1,False);
4526 /* Ensure the modtime is set correctly on the destination file. */
4527 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4530 * As we are opening fsp1 read-only we only expect
4531 * an error on close on fsp2 if we are out of space.
4532 * Thus we don't look at the error return from the
4535 *err_ret = close_file(fsp2,False);
4537 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4540 /****************************************************************************
4541 Reply to a file copy.
4542 ****************************************************************************/
4544 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4549 pstring mask,newname;
4552 int error = ERRnoaccess;
4556 int tid2 = SVAL(inbuf,smb_vwv0);
4557 int ofun = SVAL(inbuf,smb_vwv1);
4558 int flags = SVAL(inbuf,smb_vwv2);
4559 BOOL target_is_directory=False;
4560 BOOL bad_path1 = False;
4561 BOOL bad_path2 = False;
4563 SMB_STRUCT_STAT sbuf1, sbuf2;
4566 START_PROFILE(SMBcopy);
4568 *directory = *mask = 0;
4571 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4572 if (!NT_STATUS_IS_OK(status)) {
4573 END_PROFILE(SMBcopy);
4574 return ERROR_NT(status);
4576 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 END_PROFILE(SMBcopy);
4579 return ERROR_NT(status);
4582 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4584 if (tid2 != conn->cnum) {
4585 /* can't currently handle inter share copies XXXX */
4586 DEBUG(3,("Rejecting inter-share copy\n"));
4587 END_PROFILE(SMBcopy);
4588 return ERROR_DOS(ERRSRV,ERRinvdevice);
4591 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4592 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4594 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4595 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4597 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4599 if ((flags&1) && target_is_directory) {
4600 END_PROFILE(SMBcopy);
4601 return ERROR_DOS(ERRDOS,ERRbadfile);
4604 if ((flags&2) && !target_is_directory) {
4605 END_PROFILE(SMBcopy);
4606 return ERROR_DOS(ERRDOS,ERRbadpath);
4609 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4610 /* wants a tree copy! XXXX */
4611 DEBUG(3,("Rejecting tree copy\n"));
4612 END_PROFILE(SMBcopy);
4613 return ERROR_DOS(ERRSRV,ERRerror);
4616 p = strrchr_m(name,'/');
4618 pstrcpy(directory,"./");
4622 pstrcpy(directory,name);
4627 * We should only check the mangled cache
4628 * here if unix_convert failed. This means
4629 * that the path in 'mask' doesn't exist
4630 * on the file system and so we need to look
4631 * for a possible mangle. This patch from
4632 * Tine Smukavec <valentin.smukavec@hermes.si>.
4635 if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4636 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4638 has_wild = ms_has_wild(mask);
4641 pstrcat(directory,"/");
4642 pstrcat(directory,mask);
4643 if (resolve_wildcards(directory,newname) &&
4644 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4648 END_PROFILE(SMBcopy);
4649 return(UNIXERROR(ERRHRD,ERRgeneral));
4652 exists = vfs_file_exist(conn,directory,NULL);
4655 struct smb_Dir *dir_hnd = NULL;
4659 if (check_name(directory,conn))
4660 dir_hnd = OpenDir(conn, directory);
4666 if (strequal(mask,"????????.???"))
4669 while ((dname = ReadDirName(dir_hnd, &offset))) {
4671 pstrcpy(fname,dname);
4673 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4676 if(!mask_match(fname, mask, conn->case_sensitive))
4679 error = ERRnoaccess;
4680 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4681 pstrcpy(destname,newname);
4682 if (resolve_wildcards(fname,destname) &&
4683 copy_file(fname,destname,conn,ofun,
4684 count,target_is_directory,&err))
4686 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4694 /* Error on close... */
4696 END_PROFILE(SMBcopy);
4697 return(UNIXERROR(ERRHRD,ERRgeneral));
4701 END_PROFILE(SMBcopy);
4702 return ERROR_DOS(ERRDOS,error);
4704 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4705 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4707 END_PROFILE(SMBcopy);
4708 return(UNIXERROR(ERRDOS,error));
4712 outsize = set_message(outbuf,1,0,True);
4713 SSVAL(outbuf,smb_vwv0,count);
4715 END_PROFILE(SMBcopy);
4719 /****************************************************************************
4721 ****************************************************************************/
4723 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4731 START_PROFILE(pathworks_setdir);
4734 if (!CAN_SETDIR(snum)) {
4735 END_PROFILE(pathworks_setdir);
4736 return ERROR_DOS(ERRDOS,ERRnoaccess);
4739 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4740 if (!NT_STATUS_IS_OK(status)) {
4741 END_PROFILE(pathworks_setdir);
4742 return ERROR_NT(status);
4745 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4747 if (strlen(newdir) == 0) {
4750 ok = vfs_directory_exist(conn,newdir,NULL);
4752 string_set(&conn->connectpath,newdir);
4756 END_PROFILE(pathworks_setdir);
4757 return ERROR_DOS(ERRDOS,ERRbadpath);
4760 outsize = set_message(outbuf,0,0,True);
4761 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4763 DEBUG(3,("setdir %s\n", newdir));
4765 END_PROFILE(pathworks_setdir);
4770 #define DBGC_CLASS DBGC_LOCKING
4772 /****************************************************************************
4773 Get a lock pid, dealing with large count requests.
4774 ****************************************************************************/
4776 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4778 if(!large_file_format)
4779 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4781 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4784 /****************************************************************************
4785 Get a lock count, dealing with large count requests.
4786 ****************************************************************************/
4788 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4790 SMB_BIG_UINT count = 0;
4792 if(!large_file_format) {
4793 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4796 #if defined(HAVE_LONGLONG)
4797 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4798 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4799 #else /* HAVE_LONGLONG */
4802 * NT4.x seems to be broken in that it sends large file (64 bit)
4803 * lockingX calls even if the CAP_LARGE_FILES was *not*
4804 * negotiated. For boxes without large unsigned ints truncate the
4805 * lock count by dropping the top 32 bits.
4808 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4809 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4810 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4811 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4812 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4815 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4816 #endif /* HAVE_LONGLONG */
4822 #if !defined(HAVE_LONGLONG)
4823 /****************************************************************************
4824 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4825 ****************************************************************************/
4827 static uint32 map_lock_offset(uint32 high, uint32 low)
4831 uint32 highcopy = high;
4834 * Try and find out how many significant bits there are in high.
4837 for(i = 0; highcopy; i++)
4841 * We use 31 bits not 32 here as POSIX
4842 * lock offsets may not be negative.
4845 mask = (~0) << (31 - i);
4848 return 0; /* Fail. */
4854 #endif /* !defined(HAVE_LONGLONG) */
4856 /****************************************************************************
4857 Get a lock offset, dealing with large offset requests.
4858 ****************************************************************************/
4860 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4862 SMB_BIG_UINT offset = 0;
4866 if(!large_file_format) {
4867 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4870 #if defined(HAVE_LONGLONG)
4871 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4872 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4873 #else /* HAVE_LONGLONG */
4876 * NT4.x seems to be broken in that it sends large file (64 bit)
4877 * lockingX calls even if the CAP_LARGE_FILES was *not*
4878 * negotiated. For boxes without large unsigned ints mangle the
4879 * lock offset by mapping the top 32 bits onto the lower 32.
4882 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4883 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4884 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4887 if((new_low = map_lock_offset(high, low)) == 0) {
4889 return (SMB_BIG_UINT)-1;
4892 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4893 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4894 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4895 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4898 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4899 #endif /* HAVE_LONGLONG */
4905 /****************************************************************************
4906 Reply to a lockingX request.
4907 ****************************************************************************/
4909 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4911 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4912 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4913 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4914 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4915 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4916 SMB_BIG_UINT count = 0, offset = 0;
4918 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4921 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4923 BOOL my_lock_ctx = False;
4926 START_PROFILE(SMBlockingX);
4928 CHECK_FSP(fsp,conn);
4930 data = smb_buf(inbuf);
4932 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4933 /* we don't support these - and CANCEL_LOCK makes w2k
4934 and XP reboot so I don't really want to be
4935 compatible! (tridge) */
4936 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4939 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4940 /* Need to make this like a cancel.... JRA. */
4941 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4944 /* Check if this is an oplock break on a file
4945 we have granted an oplock on.
4947 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4948 /* Client can insist on breaking to none. */
4949 BOOL break_to_none = (oplocklevel == 0);
4951 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4952 (unsigned int)oplocklevel, fsp->fnum ));
4955 * Make sure we have granted an exclusive or batch oplock on this file.
4958 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4959 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4960 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4962 /* if this is a pure oplock break request then don't send a reply */
4963 if (num_locks == 0 && num_ulocks == 0) {
4964 END_PROFILE(SMBlockingX);
4967 END_PROFILE(SMBlockingX);
4968 return ERROR_DOS(ERRDOS,ERRlock);
4972 if (remove_oplock(fsp, break_to_none) == False) {
4973 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4977 /* if this is a pure oplock break request then don't send a reply */
4978 if (num_locks == 0 && num_ulocks == 0) {
4979 /* Sanity check - ensure a pure oplock break is not a
4981 if(CVAL(inbuf,smb_vwv0) != 0xff)
4982 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4983 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4984 END_PROFILE(SMBlockingX);
4990 * We do this check *after* we have checked this is not a oplock break
4991 * response message. JRA.
4994 release_level_2_oplocks_on_change(fsp);
4996 /* Data now points at the beginning of the list
4997 of smb_unlkrng structs */
4998 for(i = 0; i < (int)num_ulocks; i++) {
4999 lock_pid = get_lock_pid( data, i, large_file_format);
5000 count = get_lock_count( data, i, large_file_format);
5001 offset = get_lock_offset( data, i, large_file_format, &err);
5004 * There is no error code marked "stupid client bug".... :-).
5007 END_PROFILE(SMBlockingX);
5008 return ERROR_DOS(ERRDOS,ERRnoaccess);
5011 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
5012 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
5014 status = do_unlock(fsp,conn,lock_pid,count,offset);
5015 if (NT_STATUS_V(status)) {
5016 END_PROFILE(SMBlockingX);
5017 return ERROR_NT(status);
5021 /* Setup the timeout in seconds. */
5023 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5025 /* Now do any requested locks */
5026 data += ((large_file_format ? 20 : 10)*num_ulocks);
5028 /* Data now points at the beginning of the list
5029 of smb_lkrng structs */
5031 for(i = 0; i < (int)num_locks; i++) {
5032 lock_pid = get_lock_pid( data, i, large_file_format);
5033 count = get_lock_count( data, i, large_file_format);
5034 offset = get_lock_offset( data, i, large_file_format, &err);
5037 * There is no error code marked "stupid client bug".... :-).
5040 END_PROFILE(SMBlockingX);
5041 return ERROR_DOS(ERRDOS,ERRnoaccess);
5044 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
5045 (double)offset, (double)count, (unsigned int)lock_pid,
5046 fsp->fsp_name, (int)lock_timeout ));
5048 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
5049 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
5050 if (NT_STATUS_V(status)) {
5052 * Interesting fact found by IFSTEST /t LockOverlappedTest...
5053 * Even if it's our own lock context, we need to wait here as
5054 * there may be an unlock on the way.
5055 * So I removed a "&& !my_lock_ctx" from the following
5056 * if statement. JRA.
5058 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
5060 * A blocking lock was requested. Package up
5061 * this smb into a queued request and push it
5062 * onto the blocking lock queue.
5064 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
5065 END_PROFILE(SMBlockingX);
5073 /* If any of the above locks failed, then we must unlock
5074 all of the previous locks (X/Open spec). */
5075 if (i != num_locks && num_locks != 0) {
5077 * Ensure we don't do a remove on the lock that just failed,
5078 * as under POSIX rules, if we have a lock already there, we
5079 * will delete it (and we shouldn't) .....
5081 for(i--; i >= 0; i--) {
5082 lock_pid = get_lock_pid( data, i, large_file_format);
5083 count = get_lock_count( data, i, large_file_format);
5084 offset = get_lock_offset( data, i, large_file_format, &err);
5087 * There is no error code marked "stupid client bug".... :-).
5090 END_PROFILE(SMBlockingX);
5091 return ERROR_DOS(ERRDOS,ERRnoaccess);
5094 do_unlock(fsp,conn,lock_pid,count,offset);
5096 END_PROFILE(SMBlockingX);
5097 return ERROR_NT(status);
5100 set_message(outbuf,2,0,True);
5102 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5103 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5105 END_PROFILE(SMBlockingX);
5106 return chain_reply(inbuf,outbuf,length,bufsize);
5110 #define DBGC_CLASS DBGC_ALL
5112 /****************************************************************************
5113 Reply to a SMBreadbmpx (read block multiplex) request.
5114 ****************************************************************************/
5116 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5127 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5128 START_PROFILE(SMBreadBmpx);
5130 /* this function doesn't seem to work - disable by default */
5131 if (!lp_readbmpx()) {
5132 END_PROFILE(SMBreadBmpx);
5133 return ERROR_DOS(ERRSRV,ERRuseSTD);
5136 outsize = set_message(outbuf,8,0,True);
5138 CHECK_FSP(fsp,conn);
5141 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5142 maxcount = SVAL(inbuf,smb_vwv3);
5144 data = smb_buf(outbuf);
5145 pad = ((long)data)%4;
5150 max_per_packet = bufsize-(outsize+pad);
5154 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5155 END_PROFILE(SMBreadBmpx);
5156 return ERROR_DOS(ERRDOS,ERRlock);
5160 size_t N = MIN(max_per_packet,tcount-total_read);
5162 nread = read_file(fsp,data,startpos,N);
5167 if (nread < (ssize_t)N)
5168 tcount = total_read + nread;
5170 set_message(outbuf,8,nread,False);
5171 SIVAL(outbuf,smb_vwv0,startpos);
5172 SSVAL(outbuf,smb_vwv2,tcount);
5173 SSVAL(outbuf,smb_vwv6,nread);
5174 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5176 if (!send_smb(smbd_server_fd(),outbuf))
5177 exit_server("reply_readbmpx: send_smb failed.");
5179 total_read += nread;
5181 } while (total_read < (ssize_t)tcount);
5183 END_PROFILE(SMBreadBmpx);
5187 /****************************************************************************
5188 Reply to a SMBsetattrE.
5189 ****************************************************************************/
5191 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5193 struct utimbuf unix_times;
5195 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5196 START_PROFILE(SMBsetattrE);
5198 outsize = set_message(outbuf,0,0,True);
5200 if(!fsp || (fsp->conn != conn)) {
5201 END_PROFILE(SMBgetattrE);
5202 return ERROR_DOS(ERRDOS,ERRbadfid);
5206 * Convert the DOS times into unix times. Ignore create
5207 * time as UNIX can't set this.
5210 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5211 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5214 * Patch from Ray Frush <frush@engr.colostate.edu>
5215 * Sometimes times are sent as zero - ignore them.
5218 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5219 /* Ignore request */
5220 if( DEBUGLVL( 3 ) ) {
5221 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5222 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5224 END_PROFILE(SMBsetattrE);
5226 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5227 /* set modify time = to access time if modify time was unset */
5228 unix_times.modtime = unix_times.actime;
5231 /* Set the date on this file */
5232 /* Should we set pending modtime here ? JRA */
5233 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5234 END_PROFILE(SMBsetattrE);
5235 return ERROR_DOS(ERRDOS,ERRnoaccess);
5238 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5239 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5241 END_PROFILE(SMBsetattrE);
5246 /* Back from the dead for OS/2..... JRA. */
5248 /****************************************************************************
5249 Reply to a SMBwritebmpx (write block multiplex primary) request.
5250 ****************************************************************************/
5252 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5255 ssize_t nwritten = -1;
5262 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5263 START_PROFILE(SMBwriteBmpx);
5265 CHECK_FSP(fsp,conn);
5267 if (HAS_CACHED_ERROR(fsp)) {
5268 return(CACHED_ERROR(fsp));
5271 tcount = SVAL(inbuf,smb_vwv1);
5272 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5273 write_through = BITSETW(inbuf+smb_vwv7,0);
5274 numtowrite = SVAL(inbuf,smb_vwv10);
5275 smb_doff = SVAL(inbuf,smb_vwv11);
5277 data = smb_base(inbuf) + smb_doff;
5279 /* If this fails we need to send an SMBwriteC response,
5280 not an SMBwritebmpx - set this up now so we don't forget */
5281 SCVAL(outbuf,smb_com,SMBwritec);
5283 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5284 END_PROFILE(SMBwriteBmpx);
5285 return(ERROR_DOS(ERRDOS,ERRlock));
5288 nwritten = write_file(fsp,data,startpos,numtowrite);
5290 if(lp_syncalways(SNUM(conn)) || write_through)
5291 sync_file(conn,fsp);
5293 if(nwritten < (ssize_t)numtowrite) {
5294 END_PROFILE(SMBwriteBmpx);
5295 return(UNIXERROR(ERRHRD,ERRdiskfull));
5298 /* If the maximum to be written to this file
5299 is greater than what we just wrote then set
5300 up a secondary struct to be attached to this
5301 fd, we will use this to cache error messages etc. */
5303 if((ssize_t)tcount > nwritten) {
5304 write_bmpx_struct *wbms;
5305 if(fsp->wbmpx_ptr != NULL)
5306 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5308 wbms = SMB_MALLOC_P(write_bmpx_struct);
5310 DEBUG(0,("Out of memory in reply_readmpx\n"));
5311 END_PROFILE(SMBwriteBmpx);
5312 return(ERROR_DOS(ERRSRV,ERRnoresource));
5314 wbms->wr_mode = write_through;
5315 wbms->wr_discard = False; /* No errors yet */
5316 wbms->wr_total_written = nwritten;
5317 wbms->wr_errclass = 0;
5319 fsp->wbmpx_ptr = wbms;
5322 /* We are returning successfully, set the message type back to
5324 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5326 outsize = set_message(outbuf,1,0,True);
5328 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5330 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5331 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5333 if (write_through && tcount==nwritten) {
5334 /* We need to send both a primary and a secondary response */
5335 smb_setlen(outbuf,outsize - 4);
5336 if (!send_smb(smbd_server_fd(),outbuf))
5337 exit_server("reply_writebmpx: send_smb failed.");
5339 /* Now the secondary */
5340 outsize = set_message(outbuf,1,0,True);
5341 SCVAL(outbuf,smb_com,SMBwritec);
5342 SSVAL(outbuf,smb_vwv0,nwritten);
5345 END_PROFILE(SMBwriteBmpx);
5349 /****************************************************************************
5350 Reply to a SMBwritebs (write block multiplex secondary) request.
5351 ****************************************************************************/
5353 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5356 ssize_t nwritten = -1;
5363 write_bmpx_struct *wbms;
5364 BOOL send_response = False;
5365 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5366 START_PROFILE(SMBwriteBs);
5368 CHECK_FSP(fsp,conn);
5371 tcount = SVAL(inbuf,smb_vwv1);
5372 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5373 numtowrite = SVAL(inbuf,smb_vwv6);
5374 smb_doff = SVAL(inbuf,smb_vwv7);
5376 data = smb_base(inbuf) + smb_doff;
5378 /* We need to send an SMBwriteC response, not an SMBwritebs */
5379 SCVAL(outbuf,smb_com,SMBwritec);
5381 /* This fd should have an auxiliary struct attached,
5382 check that it does */
5383 wbms = fsp->wbmpx_ptr;
5385 END_PROFILE(SMBwriteBs);
5389 /* If write through is set we can return errors, else we must cache them */
5390 write_through = wbms->wr_mode;
5392 /* Check for an earlier error */
5393 if(wbms->wr_discard) {
5394 END_PROFILE(SMBwriteBs);
5395 return -1; /* Just discard the packet */
5398 nwritten = write_file(fsp,data,startpos,numtowrite);
5400 if(lp_syncalways(SNUM(conn)) || write_through)
5401 sync_file(conn,fsp);
5403 if (nwritten < (ssize_t)numtowrite) {
5405 /* We are returning an error - we can delete the aux struct */
5408 fsp->wbmpx_ptr = NULL;
5409 END_PROFILE(SMBwriteBs);
5410 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5412 wbms->wr_errclass = ERRHRD;
5413 wbms->wr_error = ERRdiskfull;
5414 wbms->wr_status = NT_STATUS_DISK_FULL;
5415 wbms->wr_discard = True;
5416 END_PROFILE(SMBwriteBs);
5420 /* Increment the total written, if this matches tcount
5421 we can discard the auxiliary struct (hurrah !) and return a writeC */
5422 wbms->wr_total_written += nwritten;
5423 if(wbms->wr_total_written >= tcount) {
5424 if (write_through) {
5425 outsize = set_message(outbuf,1,0,True);
5426 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5427 send_response = True;
5431 fsp->wbmpx_ptr = NULL;
5435 END_PROFILE(SMBwriteBs);
5439 END_PROFILE(SMBwriteBs);
5443 /****************************************************************************
5444 Reply to a SMBgetattrE.
5445 ****************************************************************************/
5447 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5449 SMB_STRUCT_STAT sbuf;
5452 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5453 START_PROFILE(SMBgetattrE);
5455 outsize = set_message(outbuf,11,0,True);
5457 if(!fsp || (fsp->conn != conn)) {
5458 END_PROFILE(SMBgetattrE);
5459 return ERROR_DOS(ERRDOS,ERRbadfid);
5462 /* Do an fstat on this file */
5463 if(fsp_stat(fsp, &sbuf)) {
5464 END_PROFILE(SMBgetattrE);
5465 return(UNIXERROR(ERRDOS,ERRnoaccess));
5468 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5471 * Convert the times into dos times. Set create
5472 * date to be last modify date as UNIX doesn't save
5476 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5477 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5478 /* Should we check pending modtime here ? JRA */
5479 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5482 SIVAL(outbuf,smb_vwv6,0);
5483 SIVAL(outbuf,smb_vwv8,0);
5485 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5486 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5487 SIVAL(outbuf,smb_vwv8,allocation_size);
5489 SSVAL(outbuf,smb_vwv10, mode);
5491 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5493 END_PROFILE(SMBgetattrE);