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);
2573 /* Enable when the AIO code is moved over. JRA. */
2574 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2575 END_PROFILE(SMBreadX);
2580 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2582 nread = chain_reply(inbuf,outbuf,length,bufsize);
2584 END_PROFILE(SMBreadX);
2588 /****************************************************************************
2589 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2590 ****************************************************************************/
2592 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2595 ssize_t total_written=0;
2596 size_t numtowrite=0;
2601 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2603 START_PROFILE(SMBwritebraw);
2605 if (srv_is_signing_active()) {
2606 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2609 CHECK_FSP(fsp,conn);
2612 tcount = IVAL(inbuf,smb_vwv1);
2613 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2614 write_through = BITSETW(inbuf+smb_vwv7,0);
2616 /* We have to deal with slightly different formats depending
2617 on whether we are using the core+ or lanman1.0 protocol */
2619 if(Protocol <= PROTOCOL_COREPLUS) {
2620 numtowrite = SVAL(smb_buf(inbuf),-2);
2621 data = smb_buf(inbuf);
2623 numtowrite = SVAL(inbuf,smb_vwv10);
2624 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2627 /* force the error type */
2628 SCVAL(inbuf,smb_com,SMBwritec);
2629 SCVAL(outbuf,smb_com,SMBwritec);
2631 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2632 END_PROFILE(SMBwritebraw);
2633 return(ERROR_DOS(ERRDOS,ERRlock));
2637 nwritten = write_file(fsp,data,startpos,numtowrite);
2639 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2640 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2642 if (nwritten < (ssize_t)numtowrite) {
2643 END_PROFILE(SMBwritebraw);
2644 return(UNIXERROR(ERRHRD,ERRdiskfull));
2647 total_written = nwritten;
2649 /* Return a message to the redirector to tell it to send more bytes */
2650 SCVAL(outbuf,smb_com,SMBwritebraw);
2651 SSVALS(outbuf,smb_vwv0,-1);
2652 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2654 if (!send_smb(smbd_server_fd(),outbuf))
2655 exit_server("reply_writebraw: send_smb failed.");
2657 /* Now read the raw data into the buffer and write it */
2658 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2659 exit_server("secondary writebraw failed");
2662 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2663 numtowrite = smb_len(inbuf);
2665 /* Set up outbuf to return the correct return */
2666 outsize = set_message(outbuf,1,0,True);
2667 SCVAL(outbuf,smb_com,SMBwritec);
2668 SSVAL(outbuf,smb_vwv0,total_written);
2670 if (numtowrite != 0) {
2672 if (numtowrite > BUFFER_SIZE) {
2673 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2674 (unsigned int)numtowrite ));
2675 exit_server("secondary writebraw failed");
2678 if (tcount > nwritten+numtowrite) {
2679 DEBUG(3,("Client overestimated the write %d %d %d\n",
2680 (int)tcount,(int)nwritten,(int)numtowrite));
2683 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2684 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2686 exit_server("secondary writebraw failed");
2689 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2691 if (nwritten < (ssize_t)numtowrite) {
2692 SCVAL(outbuf,smb_rcls,ERRHRD);
2693 SSVAL(outbuf,smb_err,ERRdiskfull);
2697 total_written += nwritten;
2700 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2701 sync_file(conn,fsp);
2703 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2704 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2706 /* we won't return a status if write through is not selected - this follows what WfWg does */
2707 END_PROFILE(SMBwritebraw);
2708 if (!write_through && total_written==tcount) {
2710 #if RABBIT_PELLET_FIX
2712 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2713 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2715 if (!send_keepalive(smbd_server_fd()))
2716 exit_server("reply_writebraw: send of keepalive failed");
2725 #define DBGC_CLASS DBGC_LOCKING
2727 /****************************************************************************
2728 Reply to a writeunlock (core+).
2729 ****************************************************************************/
2731 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2732 int size, int dum_buffsize)
2734 ssize_t nwritten = -1;
2738 NTSTATUS status = NT_STATUS_OK;
2739 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2741 START_PROFILE(SMBwriteunlock);
2743 CHECK_FSP(fsp,conn);
2746 numtowrite = SVAL(inbuf,smb_vwv1);
2747 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2748 data = smb_buf(inbuf) + 3;
2750 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2751 END_PROFILE(SMBwriteunlock);
2752 return ERROR_DOS(ERRDOS,ERRlock);
2755 /* The special X/Open SMB protocol handling of
2756 zero length writes is *NOT* done for
2761 nwritten = write_file(fsp,data,startpos,numtowrite);
2763 if (lp_syncalways(SNUM(conn)))
2764 sync_file(conn,fsp);
2766 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2767 END_PROFILE(SMBwriteunlock);
2768 return(UNIXERROR(ERRHRD,ERRdiskfull));
2772 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2773 (SMB_BIG_UINT)startpos);
2774 if (NT_STATUS_V(status)) {
2775 END_PROFILE(SMBwriteunlock);
2776 return ERROR_NT(status);
2780 outsize = set_message(outbuf,1,0,True);
2782 SSVAL(outbuf,smb_vwv0,nwritten);
2784 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2785 fsp->fnum, (int)numtowrite, (int)nwritten));
2787 END_PROFILE(SMBwriteunlock);
2792 #define DBGC_CLASS DBGC_ALL
2794 /****************************************************************************
2796 ****************************************************************************/
2798 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2801 ssize_t nwritten = -1;
2804 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2806 START_PROFILE(SMBwrite);
2808 /* If it's an IPC, pass off the pipe handler. */
2810 END_PROFILE(SMBwrite);
2811 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2814 CHECK_FSP(fsp,conn);
2817 numtowrite = SVAL(inbuf,smb_vwv1);
2818 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2819 data = smb_buf(inbuf) + 3;
2821 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2822 END_PROFILE(SMBwrite);
2823 return ERROR_DOS(ERRDOS,ERRlock);
2827 * X/Open SMB protocol says that if smb_vwv1 is
2828 * zero then the file size should be extended or
2829 * truncated to the size given in smb_vwv[2-3].
2832 if(numtowrite == 0) {
2834 * This is actually an allocate call, and set EOF. JRA.
2836 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2838 END_PROFILE(SMBwrite);
2839 return ERROR_NT(NT_STATUS_DISK_FULL);
2841 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2843 END_PROFILE(SMBwrite);
2844 return ERROR_NT(NT_STATUS_DISK_FULL);
2847 nwritten = write_file(fsp,data,startpos,numtowrite);
2849 if (lp_syncalways(SNUM(conn)))
2850 sync_file(conn,fsp);
2852 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2853 END_PROFILE(SMBwrite);
2854 return(UNIXERROR(ERRHRD,ERRdiskfull));
2857 outsize = set_message(outbuf,1,0,True);
2859 SSVAL(outbuf,smb_vwv0,nwritten);
2861 if (nwritten < (ssize_t)numtowrite) {
2862 SCVAL(outbuf,smb_rcls,ERRHRD);
2863 SSVAL(outbuf,smb_err,ERRdiskfull);
2866 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2868 END_PROFILE(SMBwrite);
2872 /****************************************************************************
2873 Reply to a write and X.
2874 ****************************************************************************/
2876 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2878 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2879 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2880 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2881 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2882 ssize_t nwritten = -1;
2883 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2884 unsigned int smblen = smb_len(inbuf);
2886 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2887 START_PROFILE(SMBwriteX);
2889 /* If it's an IPC, pass off the pipe handler. */
2891 END_PROFILE(SMBwriteX);
2892 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2895 CHECK_FSP(fsp,conn);
2898 set_message(outbuf,6,0,True);
2900 /* Deal with possible LARGE_WRITEX */
2902 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2905 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2906 END_PROFILE(SMBwriteX);
2907 return ERROR_DOS(ERRDOS,ERRbadmem);
2910 data = smb_base(inbuf) + smb_doff;
2912 if(CVAL(inbuf,smb_wct) == 14) {
2913 #ifdef LARGE_SMB_OFF_T
2915 * This is a large offset (64 bit) write.
2917 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2919 #else /* !LARGE_SMB_OFF_T */
2922 * Ensure we haven't been sent a >32 bit offset.
2925 if(IVAL(inbuf,smb_vwv12) != 0) {
2926 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2927 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2928 END_PROFILE(SMBwriteX);
2929 return ERROR_DOS(ERRDOS,ERRbadaccess);
2932 #endif /* LARGE_SMB_OFF_T */
2935 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2936 END_PROFILE(SMBwriteX);
2937 return ERROR_DOS(ERRDOS,ERRlock);
2940 /* X/Open SMB protocol says that, unlike SMBwrite
2941 if the length is zero then NO truncation is
2942 done, just a write of zero. To truncate a file,
2945 if(numtowrite == 0) {
2950 /* Enable when AIO code is moved over. JRA. */
2952 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2953 fsp,data,startpos,numtowrite)) {
2954 END_PROFILE(SMBwriteX);
2959 nwritten = write_file(fsp,data,startpos,numtowrite);
2962 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2963 END_PROFILE(SMBwriteX);
2964 return(UNIXERROR(ERRHRD,ERRdiskfull));
2967 SSVAL(outbuf,smb_vwv2,nwritten);
2969 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2971 if (nwritten < (ssize_t)numtowrite) {
2972 SCVAL(outbuf,smb_rcls,ERRHRD);
2973 SSVAL(outbuf,smb_err,ERRdiskfull);
2976 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2977 fsp->fnum, (int)numtowrite, (int)nwritten));
2979 if (lp_syncalways(SNUM(conn)) || write_through)
2980 sync_file(conn,fsp);
2982 END_PROFILE(SMBwriteX);
2983 return chain_reply(inbuf,outbuf,length,bufsize);
2986 /****************************************************************************
2988 ****************************************************************************/
2990 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2996 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2997 START_PROFILE(SMBlseek);
2999 CHECK_FSP(fsp,conn);
3001 flush_write_cache(fsp, SEEK_FLUSH);
3003 mode = SVAL(inbuf,smb_vwv1) & 3;
3004 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3005 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3014 res = fsp->pos + startpos;
3025 if (umode == SEEK_END) {
3026 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
3027 if(errno == EINVAL) {
3028 SMB_OFF_T current_pos = startpos;
3029 SMB_STRUCT_STAT sbuf;
3031 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
3032 END_PROFILE(SMBlseek);
3033 return(UNIXERROR(ERRDOS,ERRnoaccess));
3036 current_pos += sbuf.st_size;
3038 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
3043 END_PROFILE(SMBlseek);
3044 return(UNIXERROR(ERRDOS,ERRnoaccess));
3050 outsize = set_message(outbuf,2,0,True);
3051 SIVAL(outbuf,smb_vwv0,res);
3053 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3054 fsp->fnum, (double)startpos, (double)res, mode));
3056 END_PROFILE(SMBlseek);
3060 /****************************************************************************
3062 ****************************************************************************/
3064 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3066 int outsize = set_message(outbuf,0,0,True);
3067 uint16 fnum = SVAL(inbuf,smb_vwv0);
3068 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3069 START_PROFILE(SMBflush);
3072 CHECK_FSP(fsp,conn);
3075 file_sync_all(conn);
3077 sync_file(conn,fsp);
3080 DEBUG(3,("flush\n"));
3081 END_PROFILE(SMBflush);
3085 /****************************************************************************
3087 ****************************************************************************/
3089 int reply_exit(connection_struct *conn,
3090 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3093 START_PROFILE(SMBexit);
3095 file_close_pid(SVAL(inbuf,smb_pid));
3097 outsize = set_message(outbuf,0,0,True);
3099 DEBUG(3,("exit\n"));
3101 END_PROFILE(SMBexit);
3105 /****************************************************************************
3106 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3107 ****************************************************************************/
3109 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3114 int32 eclass = 0, err = 0;
3115 files_struct *fsp = NULL;
3116 START_PROFILE(SMBclose);
3118 outsize = set_message(outbuf,0,0,True);
3120 /* If it's an IPC, pass off to the pipe handler. */
3122 END_PROFILE(SMBclose);
3123 return reply_pipe_close(conn, inbuf,outbuf);
3126 fsp = file_fsp(inbuf,smb_vwv0);
3129 * We can only use CHECK_FSP if we know it's not a directory.
3132 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3133 END_PROFILE(SMBclose);
3134 return ERROR_DOS(ERRDOS,ERRbadfid);
3137 if(fsp->is_directory) {
3139 * Special case - close NT SMB directory handle.
3141 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3142 close_file(fsp,True);
3145 * Close ordinary file.
3150 /* Save the name for time set in close. */
3151 pstrcpy( file_name, fsp->fsp_name);
3153 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3155 conn->num_files_open));
3158 * Take care of any time sent in the close.
3161 mtime = make_unix_date3(inbuf+smb_vwv1);
3162 fsp_set_pending_modtime(fsp, mtime);
3165 * close_file() returns the unix errno if an error
3166 * was detected on close - normally this is due to
3167 * a disk full error. If not then it was probably an I/O error.
3170 if((close_err = close_file(fsp,True)) != 0) {
3172 END_PROFILE(SMBclose);
3173 return (UNIXERROR(ERRHRD,ERRgeneral));
3177 /* We have a cached error */
3179 END_PROFILE(SMBclose);
3180 return ERROR_DOS(eclass,err);
3183 END_PROFILE(SMBclose);
3187 /****************************************************************************
3188 Reply to a writeclose (Core+ protocol).
3189 ****************************************************************************/
3191 int reply_writeclose(connection_struct *conn,
3192 char *inbuf,char *outbuf, int size, int dum_buffsize)
3195 ssize_t nwritten = -1;
3201 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3202 START_PROFILE(SMBwriteclose);
3204 CHECK_FSP(fsp,conn);
3207 numtowrite = SVAL(inbuf,smb_vwv1);
3208 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3209 mtime = make_unix_date3(inbuf+smb_vwv4);
3210 data = smb_buf(inbuf) + 1;
3212 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3213 END_PROFILE(SMBwriteclose);
3214 return ERROR_DOS(ERRDOS,ERRlock);
3217 nwritten = write_file(fsp,data,startpos,numtowrite);
3219 set_filetime(conn, fsp->fsp_name,mtime);
3222 * More insanity. W2K only closes the file if writelen > 0.
3227 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3229 close_err = close_file(fsp,True);
3232 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3233 fsp->fnum, (int)numtowrite, (int)nwritten,
3234 conn->num_files_open));
3236 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3237 END_PROFILE(SMBwriteclose);
3238 return(UNIXERROR(ERRHRD,ERRdiskfull));
3241 if(close_err != 0) {
3243 END_PROFILE(SMBwriteclose);
3244 return(UNIXERROR(ERRHRD,ERRgeneral));
3247 outsize = set_message(outbuf,1,0,True);
3249 SSVAL(outbuf,smb_vwv0,nwritten);
3250 END_PROFILE(SMBwriteclose);
3255 #define DBGC_CLASS DBGC_LOCKING
3257 /****************************************************************************
3259 ****************************************************************************/
3261 int reply_lock(connection_struct *conn,
3262 char *inbuf,char *outbuf, int length, int dum_buffsize)
3264 int outsize = set_message(outbuf,0,0,True);
3265 SMB_BIG_UINT count,offset;
3267 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3268 BOOL my_lock_ctx = False;
3270 START_PROFILE(SMBlock);
3272 CHECK_FSP(fsp,conn);
3274 release_level_2_oplocks_on_change(fsp);
3276 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3277 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3279 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3280 fsp->fd, fsp->fnum, (double)offset, (double)count));
3282 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3283 if (NT_STATUS_V(status)) {
3285 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3286 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3288 * A blocking lock was requested. Package up
3289 * this smb into a queued request and push it
3290 * onto the blocking lock queue.
3292 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3293 END_PROFILE(SMBlock);
3298 END_PROFILE(SMBlock);
3299 return ERROR_NT(status);
3302 END_PROFILE(SMBlock);
3306 /****************************************************************************
3308 ****************************************************************************/
3310 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3313 int outsize = set_message(outbuf,0,0,True);
3314 SMB_BIG_UINT count,offset;
3316 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3317 START_PROFILE(SMBunlock);
3319 CHECK_FSP(fsp,conn);
3321 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3322 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3324 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3325 if (NT_STATUS_V(status)) {
3326 END_PROFILE(SMBunlock);
3327 return ERROR_NT(status);
3330 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3331 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3333 END_PROFILE(SMBunlock);
3338 #define DBGC_CLASS DBGC_ALL
3340 /****************************************************************************
3342 ****************************************************************************/
3344 int reply_tdis(connection_struct *conn,
3345 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3347 int outsize = set_message(outbuf,0,0,True);
3349 START_PROFILE(SMBtdis);
3351 vuid = SVAL(inbuf,smb_uid);
3354 DEBUG(4,("Invalid connection in tdis\n"));
3355 END_PROFILE(SMBtdis);
3356 return ERROR_DOS(ERRSRV,ERRinvnid);
3361 close_cnum(conn,vuid);
3363 END_PROFILE(SMBtdis);
3367 /****************************************************************************
3369 ****************************************************************************/
3371 int reply_echo(connection_struct *conn,
3372 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3374 int smb_reverb = SVAL(inbuf,smb_vwv0);
3376 unsigned int data_len = smb_buflen(inbuf);
3377 int outsize = set_message(outbuf,1,data_len,True);
3378 START_PROFILE(SMBecho);
3380 if (data_len > BUFFER_SIZE) {
3381 DEBUG(0,("reply_echo: data_len too large.\n"));
3382 END_PROFILE(SMBecho);
3386 /* copy any incoming data back out */
3388 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3390 if (smb_reverb > 100) {
3391 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3395 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3396 SSVAL(outbuf,smb_vwv0,seq_num);
3398 smb_setlen(outbuf,outsize - 4);
3401 if (!send_smb(smbd_server_fd(),outbuf))
3402 exit_server("reply_echo: send_smb failed.");
3405 DEBUG(3,("echo %d times\n", smb_reverb));
3409 END_PROFILE(SMBecho);
3413 /****************************************************************************
3414 Reply to a printopen.
3415 ****************************************************************************/
3417 int reply_printopen(connection_struct *conn,
3418 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3422 START_PROFILE(SMBsplopen);
3424 if (!CAN_PRINT(conn)) {
3425 END_PROFILE(SMBsplopen);
3426 return ERROR_DOS(ERRDOS,ERRnoaccess);
3429 /* Open for exclusive use, write only. */
3430 fsp = print_fsp_open(conn, NULL);
3433 END_PROFILE(SMBsplopen);
3434 return(UNIXERROR(ERRDOS,ERRnoaccess));
3437 outsize = set_message(outbuf,1,0,True);
3438 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3440 DEBUG(3,("openprint fd=%d fnum=%d\n",
3441 fsp->fd, fsp->fnum));
3443 END_PROFILE(SMBsplopen);
3447 /****************************************************************************
3448 Reply to a printclose.
3449 ****************************************************************************/
3451 int reply_printclose(connection_struct *conn,
3452 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3454 int outsize = set_message(outbuf,0,0,True);
3455 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3457 START_PROFILE(SMBsplclose);
3459 CHECK_FSP(fsp,conn);
3461 if (!CAN_PRINT(conn)) {
3462 END_PROFILE(SMBsplclose);
3463 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3466 DEBUG(3,("printclose fd=%d fnum=%d\n",
3467 fsp->fd,fsp->fnum));
3469 close_err = close_file(fsp,True);
3471 if(close_err != 0) {
3473 END_PROFILE(SMBsplclose);
3474 return(UNIXERROR(ERRHRD,ERRgeneral));
3477 END_PROFILE(SMBsplclose);
3481 /****************************************************************************
3482 Reply to a printqueue.
3483 ****************************************************************************/
3485 int reply_printqueue(connection_struct *conn,
3486 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3488 int outsize = set_message(outbuf,2,3,True);
3489 int max_count = SVAL(inbuf,smb_vwv0);
3490 int start_index = SVAL(inbuf,smb_vwv1);
3491 START_PROFILE(SMBsplretq);
3493 /* we used to allow the client to get the cnum wrong, but that
3494 is really quite gross and only worked when there was only
3495 one printer - I think we should now only accept it if they
3496 get it right (tridge) */
3497 if (!CAN_PRINT(conn)) {
3498 END_PROFILE(SMBsplretq);
3499 return ERROR_DOS(ERRDOS,ERRnoaccess);
3502 SSVAL(outbuf,smb_vwv0,0);
3503 SSVAL(outbuf,smb_vwv1,0);
3504 SCVAL(smb_buf(outbuf),0,1);
3505 SSVAL(smb_buf(outbuf),1,0);
3507 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3508 start_index, max_count));
3511 print_queue_struct *queue = NULL;
3512 print_status_struct status;
3513 char *p = smb_buf(outbuf) + 3;
3514 int count = print_queue_status(SNUM(conn), &queue, &status);
3515 int num_to_get = ABS(max_count);
3516 int first = (max_count>0?start_index:start_index+max_count+1);
3522 num_to_get = MIN(num_to_get,count-first);
3525 for (i=first;i<first+num_to_get;i++) {
3526 put_dos_date2(p,0,queue[i].time);
3527 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3528 SSVAL(p,5, queue[i].job);
3529 SIVAL(p,7,queue[i].size);
3531 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3536 outsize = set_message(outbuf,2,28*count+3,False);
3537 SSVAL(outbuf,smb_vwv0,count);
3538 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3539 SCVAL(smb_buf(outbuf),0,1);
3540 SSVAL(smb_buf(outbuf),1,28*count);
3545 DEBUG(3,("%d entries returned in queue\n",count));
3548 END_PROFILE(SMBsplretq);
3552 /****************************************************************************
3553 Reply to a printwrite.
3554 ****************************************************************************/
3556 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3559 int outsize = set_message(outbuf,0,0,True);
3561 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3563 START_PROFILE(SMBsplwr);
3565 if (!CAN_PRINT(conn)) {
3566 END_PROFILE(SMBsplwr);
3567 return ERROR_DOS(ERRDOS,ERRnoaccess);
3570 CHECK_FSP(fsp,conn);
3573 numtowrite = SVAL(smb_buf(inbuf),1);
3574 data = smb_buf(inbuf) + 3;
3576 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3577 END_PROFILE(SMBsplwr);
3578 return(UNIXERROR(ERRHRD,ERRdiskfull));
3581 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3583 END_PROFILE(SMBsplwr);
3587 /****************************************************************************
3588 The guts of the mkdir command, split out so it may be called by the NT SMB
3590 ****************************************************************************/
3592 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3596 if(!CAN_WRITE(conn)) {
3597 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3599 return map_nt_error_from_unix(errno);
3603 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3606 if (!check_name(directory, conn)) {
3607 if(errno == ENOENT) {
3609 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3611 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3614 return map_nt_error_from_unix(errno);
3617 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3619 if(errno == ENOENT) {
3620 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3622 return map_nt_error_from_unix(errno);
3625 return NT_STATUS_OK;
3628 /****************************************************************************
3630 ****************************************************************************/
3632 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3637 BOOL bad_path = False;
3638 SMB_STRUCT_STAT sbuf;
3640 START_PROFILE(SMBmkdir);
3642 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3643 if (!NT_STATUS_IS_OK(status)) {
3644 END_PROFILE(SMBmkdir);
3645 return ERROR_NT(status);
3648 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3650 unix_convert(directory,conn,0,&bad_path,&sbuf);
3652 if( is_ntfs_stream_name(directory)) {
3653 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3654 END_PROFILE(SMBmkdir);
3655 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3658 status = mkdir_internal(conn, directory,bad_path);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 END_PROFILE(SMBmkdir);
3661 return ERROR_NT(status);
3664 if (lp_inherit_owner(SNUM(conn))) {
3665 /* Ensure we're checking for a symlink here.... */
3666 /* We don't want to get caught by a symlink racer. */
3668 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3669 END_PROFILE(SMBmkdir);
3670 return(UNIXERROR(ERRDOS,ERRnoaccess));
3673 if(!S_ISDIR(sbuf.st_mode)) {
3674 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3675 END_PROFILE(SMBmkdir);
3676 return(UNIXERROR(ERRDOS,ERRnoaccess));
3679 change_owner_to_parent(conn, NULL, directory, &sbuf);
3682 outsize = set_message(outbuf,0,0,True);
3684 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3686 END_PROFILE(SMBmkdir);
3690 /****************************************************************************
3691 Static function used by reply_rmdir to delete an entire directory
3692 tree recursively. Return False on ok, True on fail.
3693 ****************************************************************************/
3695 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3697 const char *dname = NULL;
3700 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3705 while((dname = ReadDirName(dir_hnd, &offset))) {
3709 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3712 if (!is_visible_file(conn, directory, dname, &st, False))
3715 /* Construct the full name. */
3716 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3722 pstrcpy(fullname, directory);
3723 pstrcat(fullname, "/");
3724 pstrcat(fullname, dname);
3726 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3731 if(st.st_mode & S_IFDIR) {
3732 if(recursive_rmdir(conn, fullname)!=0) {
3736 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3740 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3749 /****************************************************************************
3750 The internals of the rmdir code - called elsewhere.
3751 ****************************************************************************/
3753 BOOL rmdir_internals(connection_struct *conn, char *directory)
3758 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3759 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3761 * Check to see if the only thing in this directory are
3762 * vetoed files/directories. If so then delete them and
3763 * retry. If we fail to delete any of them (and we *don't*
3764 * do a recursive delete) then fail the rmdir.
3766 BOOL all_veto_files = True;
3768 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3770 if(dir_hnd != NULL) {
3771 long dirpos = TellDir(dir_hnd);
3772 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3773 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3775 if (!is_visible_file(conn, directory, dname, &st, False))
3777 if(!IS_VETO_PATH(conn, dname)) {
3778 all_veto_files = False;
3783 if(all_veto_files) {
3784 SeekDir(dir_hnd,dirpos);
3785 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3788 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3790 if (!is_visible_file(conn, directory, dname, &st, False))
3793 /* Construct the full name. */
3794 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3799 pstrcpy(fullname, directory);
3800 pstrcat(fullname, "/");
3801 pstrcat(fullname, dname);
3803 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3805 if(st.st_mode & S_IFDIR) {
3806 if(lp_recursive_veto_delete(SNUM(conn))) {
3807 if(recursive_rmdir(conn, fullname) != 0)
3810 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3812 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3816 /* Retry the rmdir */
3817 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3827 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3832 /****************************************************************************
3834 ****************************************************************************/
3836 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3841 BOOL bad_path = False;
3842 SMB_STRUCT_STAT sbuf;
3844 START_PROFILE(SMBrmdir);
3846 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3847 if (!NT_STATUS_IS_OK(status)) {
3848 END_PROFILE(SMBrmdir);
3849 return ERROR_NT(status);
3852 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3854 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3856 END_PROFILE(SMBrmdir);
3857 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3860 if (check_name(directory,conn)) {
3861 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3862 ok = rmdir_internals(conn, directory);
3866 END_PROFILE(SMBrmdir);
3867 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3870 outsize = set_message(outbuf,0,0,True);
3872 DEBUG( 3, ( "rmdir %s\n", directory ) );
3874 END_PROFILE(SMBrmdir);
3878 /*******************************************************************
3879 Resolve wildcards in a filename rename.
3880 Note that name is in UNIX charset and thus potentially can be more
3881 than fstring buffer (255 bytes) especially in default UTF-8 case.
3882 Therefore, we use pstring inside and all calls should ensure that
3883 name2 is at least pstring-long (they do already)
3884 ********************************************************************/
3886 static BOOL resolve_wildcards(const char *name1, char *name2)
3888 pstring root1,root2;
3890 char *p,*p2, *pname1, *pname2;
3891 int available_space, actual_space;
3894 pname1 = strrchr_m(name1,'/');
3895 pname2 = strrchr_m(name2,'/');
3897 if (!pname1 || !pname2)
3900 pstrcpy(root1,pname1);
3901 pstrcpy(root2,pname2);
3902 p = strrchr_m(root1,'.');
3909 p = strrchr_m(root2,'.');
3923 } else if (*p2 == '*') {
3939 } else if (*p2 == '*') {
3949 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3952 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3953 if (actual_space >= available_space - 1) {
3954 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3955 actual_space - available_space));
3958 pstrcpy_base(pname2, root2, name2);
3964 /****************************************************************************
3965 Ensure open files have their names updates.
3966 ****************************************************************************/
3968 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3971 BOOL did_rename = False;
3973 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3974 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3975 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3976 fsp->fsp_name, newname ));
3977 string_set(&fsp->fsp_name, newname);
3982 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3983 (unsigned int)dev, (double)inode, newname ));
3986 /****************************************************************************
3987 Rename an open file - given an fsp.
3988 ****************************************************************************/
3990 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3992 SMB_STRUCT_STAT sbuf;
3993 BOOL bad_path = False;
3994 pstring newname_last_component;
3995 NTSTATUS error = NT_STATUS_OK;
4000 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
4002 /* Quick check for "." and ".." */
4003 if (!bad_path && newname_last_component[0] == '.') {
4004 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
4005 return NT_STATUS_ACCESS_DENIED;
4008 if (!rcdest && bad_path) {
4009 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4012 /* Ensure newname contains a '/' */
4013 if(strrchr_m(newname,'/') == 0) {
4016 pstrcpy(tmpstr, "./");
4017 pstrcat(tmpstr, newname);
4018 pstrcpy(newname, tmpstr);
4022 * Check for special case with case preserving and not
4023 * case sensitive. If the old last component differs from the original
4024 * last component only by case, then we should allow
4025 * the rename (user is trying to change the case of the
4029 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4030 strequal(newname, fsp->fsp_name)) {
4032 pstring newname_modified_last_component;
4035 * Get the last component of the modified name.
4036 * Note that we guarantee that newname contains a '/'
4039 p = strrchr_m(newname,'/');
4040 pstrcpy(newname_modified_last_component,p+1);
4042 if(strcsequal(newname_modified_last_component,
4043 newname_last_component) == False) {
4045 * Replace the modified last component with
4048 pstrcpy(p+1, newname_last_component);
4053 * If the src and dest names are identical - including case,
4054 * don't do the rename, just return success.
4057 if (strcsequal(fsp->fsp_name, newname)) {
4058 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4060 return NT_STATUS_OK;
4063 dest_exists = vfs_object_exist(conn,newname,NULL);
4065 if(!replace_if_exists && dest_exists) {
4066 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4067 fsp->fsp_name,newname));
4068 return NT_STATUS_OBJECT_NAME_COLLISION;
4071 error = can_rename(conn,newname,attrs,&sbuf);
4073 if (dest_exists && !NT_STATUS_IS_OK(error)) {
4074 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4075 nt_errstr(error), fsp->fsp_name,newname));
4076 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4077 error = NT_STATUS_ACCESS_DENIED;
4081 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4082 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4083 fsp->fsp_name,newname));
4084 rename_open_files(conn, fsp->dev, fsp->inode, newname);
4085 return NT_STATUS_OK;
4088 if (errno == ENOTDIR || errno == EISDIR)
4089 error = NT_STATUS_OBJECT_NAME_COLLISION;
4091 error = map_nt_error_from_unix(errno);
4093 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4094 nt_errstr(error), fsp->fsp_name,newname));
4099 /****************************************************************************
4100 The guts of the rename command, split out so it may be called by the NT SMB
4102 ****************************************************************************/
4104 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
4108 pstring last_component_src;
4109 pstring last_component_dest;
4112 BOOL bad_path_src = False;
4113 BOOL bad_path_dest = False;
4115 NTSTATUS error = NT_STATUS_OK;
4118 SMB_STRUCT_STAT sbuf1, sbuf2;
4120 *directory = *mask = 0;
4125 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4126 if (!rc && bad_path_src) {
4127 if (ms_has_wild(last_component_src))
4128 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4129 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4132 /* Quick check for "." and ".." */
4133 if (last_component_src[0] == '.') {
4134 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4135 return NT_STATUS_OBJECT_NAME_INVALID;
4139 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4141 /* Quick check for "." and ".." */
4142 if (last_component_dest[0] == '.') {
4143 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4144 return NT_STATUS_OBJECT_NAME_INVALID;
4149 * Split the old name into directory and last component
4150 * strings. Note that unix_convert may have stripped off a
4151 * leading ./ from both name and newname if the rename is
4152 * at the root of the share. We need to make sure either both
4153 * name and newname contain a / character or neither of them do
4154 * as this is checked in resolve_wildcards().
4157 p = strrchr_m(name,'/');
4159 pstrcpy(directory,".");
4163 pstrcpy(directory,name);
4165 *p = '/'; /* Replace needed for exceptional test below. */
4169 * We should only check the mangled cache
4170 * here if unix_convert failed. This means
4171 * that the path in 'mask' doesn't exist
4172 * on the file system and so we need to look
4173 * for a possible mangle. This patch from
4174 * Tine Smukavec <valentin.smukavec@hermes.si>.
4177 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4178 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4180 has_wild = ms_has_wild(mask);
4184 * No wildcards - just process the one file.
4186 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4188 /* Add a terminating '/' to the directory name. */
4189 pstrcat(directory,"/");
4190 pstrcat(directory,mask);
4192 /* Ensure newname contains a '/' also */
4193 if(strrchr_m(newname,'/') == 0) {
4196 pstrcpy(tmpstr, "./");
4197 pstrcat(tmpstr, newname);
4198 pstrcpy(newname, tmpstr);
4201 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4202 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4203 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4204 newname, last_component_dest, is_short_name));
4207 * Check for special case with case preserving and not
4208 * case sensitive, if directory and newname are identical,
4209 * and the old last component differs from the original
4210 * last component only by case, then we should allow
4211 * the rename (user is trying to change the case of the
4214 if((conn->case_sensitive == False) &&
4215 (((conn->case_preserve == True) &&
4216 (is_short_name == False)) ||
4217 ((conn->short_case_preserve == True) &&
4218 (is_short_name == True))) &&
4219 strcsequal(directory, newname)) {
4220 pstring modified_last_component;
4223 * Get the last component of the modified name.
4224 * Note that we guarantee that newname contains a '/'
4227 p = strrchr_m(newname,'/');
4228 pstrcpy(modified_last_component,p+1);
4230 if(strcsequal(modified_last_component,
4231 last_component_dest) == False) {
4233 * Replace the modified last component with
4236 pstrcpy(p+1, last_component_dest);
4240 resolve_wildcards(directory,newname);
4243 * The source object must exist.
4246 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4247 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4248 directory,newname));
4250 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4252 * Must return different errors depending on whether the parent
4253 * directory existed or not.
4256 p = strrchr_m(directory, '/');
4258 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4260 if (vfs_object_exist(conn, directory, NULL))
4261 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4262 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4264 error = map_nt_error_from_unix(errno);
4265 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4266 nt_errstr(error), directory,newname));
4271 if (!rcdest && bad_path_dest) {
4272 if (ms_has_wild(last_component_dest))
4273 return NT_STATUS_OBJECT_NAME_INVALID;
4274 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4277 error = can_rename(conn,directory,attrs,&sbuf1);
4279 if (!NT_STATUS_IS_OK(error)) {
4280 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4281 nt_errstr(error), directory,newname));
4286 * If the src and dest names are identical - including case,
4287 * don't do the rename, just return success.
4290 if (strcsequal(directory, newname)) {
4291 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4292 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4293 return NT_STATUS_OK;
4296 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4297 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4298 directory,newname));
4299 return NT_STATUS_OBJECT_NAME_COLLISION;
4302 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4303 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4304 directory,newname));
4305 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4306 return NT_STATUS_OK;
4309 if (errno == ENOTDIR || errno == EISDIR)
4310 error = NT_STATUS_OBJECT_NAME_COLLISION;
4312 error = map_nt_error_from_unix(errno);
4314 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4315 nt_errstr(error), directory,newname));
4320 * Wildcards - process each file that matches.
4322 struct smb_Dir *dir_hnd = NULL;
4326 if (check_name(directory,conn))
4327 dir_hnd = OpenDir(conn, directory);
4331 error = NT_STATUS_NO_SUCH_FILE;
4332 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4334 if (strequal(mask,"????????.???"))
4337 while ((dname = ReadDirName(dir_hnd, &offset))) {
4339 BOOL sysdir_entry = False;
4341 pstrcpy(fname,dname);
4343 /* Quick check for "." and ".." */
4344 if (fname[0] == '.') {
4345 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4347 sysdir_entry = True;
4354 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4357 if(!mask_match(fname, mask, conn->case_sensitive))
4361 error = NT_STATUS_OBJECT_NAME_INVALID;
4365 error = NT_STATUS_ACCESS_DENIED;
4366 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4367 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4368 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4369 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4372 error = can_rename(conn,fname,attrs,&sbuf1);
4373 if (!NT_STATUS_IS_OK(error)) {
4374 DEBUG(6,("rename %s refused\n", fname));
4377 pstrcpy(destname,newname);
4379 if (!resolve_wildcards(fname,destname)) {
4380 DEBUG(6,("resolve_wildcards %s %s failed\n",
4385 if (strcsequal(fname,destname)) {
4386 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4387 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4389 error = NT_STATUS_OK;
4393 if (!replace_if_exists &&
4394 vfs_file_exist(conn,destname, NULL)) {
4395 DEBUG(6,("file_exist %s\n", destname));
4396 error = NT_STATUS_OBJECT_NAME_COLLISION;
4400 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4401 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4403 error = NT_STATUS_OK;
4405 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4410 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4411 if (!rcdest && bad_path_dest) {
4412 if (ms_has_wild(last_component_dest))
4413 return NT_STATUS_OBJECT_NAME_INVALID;
4414 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4419 if (count == 0 && NT_STATUS_IS_OK(error)) {
4420 error = map_nt_error_from_unix(errno);
4426 /****************************************************************************
4428 ****************************************************************************/
4430 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4437 uint16 attrs = SVAL(inbuf,smb_vwv0);
4440 START_PROFILE(SMBmv);
4442 p = smb_buf(inbuf) + 1;
4443 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4444 if (!NT_STATUS_IS_OK(status)) {
4446 return ERROR_NT(status);
4449 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4450 if (!NT_STATUS_IS_OK(status)) {
4452 return ERROR_NT(status);
4455 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4456 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4458 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4460 status = rename_internals(conn, name, newname, attrs, False);
4461 if (!NT_STATUS_IS_OK(status)) {
4463 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4464 /* We have re-scheduled this call. */
4467 return ERROR_NT(status);
4471 * Win2k needs a changenotify request response before it will
4472 * update after a rename..
4474 process_pending_change_notify_queue((time_t)0);
4475 outsize = set_message(outbuf,0,0,True);
4481 /*******************************************************************
4482 Copy a file as part of a reply_copy.
4483 ******************************************************************/
4485 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4486 int count,BOOL target_is_directory, int *err_ret)
4489 SMB_STRUCT_STAT src_sbuf, sbuf2;
4491 files_struct *fsp1,*fsp2;
4497 pstrcpy(dest,dest1);
4498 if (target_is_directory) {
4499 char *p = strrchr_m(src,'/');
4508 if (!vfs_file_exist(conn,src,&src_sbuf))
4511 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4512 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4518 if (!target_is_directory && count)
4519 ofun = FILE_EXISTS_OPEN;
4521 dosattrs = dos_mode(conn, src, &src_sbuf);
4522 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4523 ZERO_STRUCTP(&sbuf2);
4525 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4526 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4529 close_file(fsp1,False);
4533 if ((ofun&3) == 1) {
4534 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4535 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4537 * Stop the copy from occurring.
4540 src_sbuf.st_size = 0;
4544 if (src_sbuf.st_size)
4545 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4547 close_file(fsp1,False);
4549 /* Ensure the modtime is set correctly on the destination file. */
4550 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4553 * As we are opening fsp1 read-only we only expect
4554 * an error on close on fsp2 if we are out of space.
4555 * Thus we don't look at the error return from the
4558 *err_ret = close_file(fsp2,False);
4560 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4563 /****************************************************************************
4564 Reply to a file copy.
4565 ****************************************************************************/
4567 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4572 pstring mask,newname;
4575 int error = ERRnoaccess;
4579 int tid2 = SVAL(inbuf,smb_vwv0);
4580 int ofun = SVAL(inbuf,smb_vwv1);
4581 int flags = SVAL(inbuf,smb_vwv2);
4582 BOOL target_is_directory=False;
4583 BOOL bad_path1 = False;
4584 BOOL bad_path2 = False;
4586 SMB_STRUCT_STAT sbuf1, sbuf2;
4589 START_PROFILE(SMBcopy);
4591 *directory = *mask = 0;
4594 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4595 if (!NT_STATUS_IS_OK(status)) {
4596 END_PROFILE(SMBcopy);
4597 return ERROR_NT(status);
4599 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4600 if (!NT_STATUS_IS_OK(status)) {
4601 END_PROFILE(SMBcopy);
4602 return ERROR_NT(status);
4605 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4607 if (tid2 != conn->cnum) {
4608 /* can't currently handle inter share copies XXXX */
4609 DEBUG(3,("Rejecting inter-share copy\n"));
4610 END_PROFILE(SMBcopy);
4611 return ERROR_DOS(ERRSRV,ERRinvdevice);
4614 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4615 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4617 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4618 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4620 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4622 if ((flags&1) && target_is_directory) {
4623 END_PROFILE(SMBcopy);
4624 return ERROR_DOS(ERRDOS,ERRbadfile);
4627 if ((flags&2) && !target_is_directory) {
4628 END_PROFILE(SMBcopy);
4629 return ERROR_DOS(ERRDOS,ERRbadpath);
4632 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4633 /* wants a tree copy! XXXX */
4634 DEBUG(3,("Rejecting tree copy\n"));
4635 END_PROFILE(SMBcopy);
4636 return ERROR_DOS(ERRSRV,ERRerror);
4639 p = strrchr_m(name,'/');
4641 pstrcpy(directory,"./");
4645 pstrcpy(directory,name);
4650 * We should only check the mangled cache
4651 * here if unix_convert failed. This means
4652 * that the path in 'mask' doesn't exist
4653 * on the file system and so we need to look
4654 * for a possible mangle. This patch from
4655 * Tine Smukavec <valentin.smukavec@hermes.si>.
4658 if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4659 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4661 has_wild = ms_has_wild(mask);
4664 pstrcat(directory,"/");
4665 pstrcat(directory,mask);
4666 if (resolve_wildcards(directory,newname) &&
4667 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4671 END_PROFILE(SMBcopy);
4672 return(UNIXERROR(ERRHRD,ERRgeneral));
4675 exists = vfs_file_exist(conn,directory,NULL);
4678 struct smb_Dir *dir_hnd = NULL;
4682 if (check_name(directory,conn))
4683 dir_hnd = OpenDir(conn, directory);
4689 if (strequal(mask,"????????.???"))
4692 while ((dname = ReadDirName(dir_hnd, &offset))) {
4694 pstrcpy(fname,dname);
4696 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4699 if(!mask_match(fname, mask, conn->case_sensitive))
4702 error = ERRnoaccess;
4703 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4704 pstrcpy(destname,newname);
4705 if (resolve_wildcards(fname,destname) &&
4706 copy_file(fname,destname,conn,ofun,
4707 count,target_is_directory,&err))
4709 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4717 /* Error on close... */
4719 END_PROFILE(SMBcopy);
4720 return(UNIXERROR(ERRHRD,ERRgeneral));
4724 END_PROFILE(SMBcopy);
4725 return ERROR_DOS(ERRDOS,error);
4727 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4728 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4730 END_PROFILE(SMBcopy);
4731 return(UNIXERROR(ERRDOS,error));
4735 outsize = set_message(outbuf,1,0,True);
4736 SSVAL(outbuf,smb_vwv0,count);
4738 END_PROFILE(SMBcopy);
4742 /****************************************************************************
4744 ****************************************************************************/
4746 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4754 START_PROFILE(pathworks_setdir);
4757 if (!CAN_SETDIR(snum)) {
4758 END_PROFILE(pathworks_setdir);
4759 return ERROR_DOS(ERRDOS,ERRnoaccess);
4762 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4763 if (!NT_STATUS_IS_OK(status)) {
4764 END_PROFILE(pathworks_setdir);
4765 return ERROR_NT(status);
4768 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4770 if (strlen(newdir) == 0) {
4773 ok = vfs_directory_exist(conn,newdir,NULL);
4775 string_set(&conn->connectpath,newdir);
4779 END_PROFILE(pathworks_setdir);
4780 return ERROR_DOS(ERRDOS,ERRbadpath);
4783 outsize = set_message(outbuf,0,0,True);
4784 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4786 DEBUG(3,("setdir %s\n", newdir));
4788 END_PROFILE(pathworks_setdir);
4793 #define DBGC_CLASS DBGC_LOCKING
4795 /****************************************************************************
4796 Get a lock pid, dealing with large count requests.
4797 ****************************************************************************/
4799 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4801 if(!large_file_format)
4802 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4804 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4807 /****************************************************************************
4808 Get a lock count, dealing with large count requests.
4809 ****************************************************************************/
4811 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4813 SMB_BIG_UINT count = 0;
4815 if(!large_file_format) {
4816 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4819 #if defined(HAVE_LONGLONG)
4820 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4821 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4822 #else /* HAVE_LONGLONG */
4825 * NT4.x seems to be broken in that it sends large file (64 bit)
4826 * lockingX calls even if the CAP_LARGE_FILES was *not*
4827 * negotiated. For boxes without large unsigned ints truncate the
4828 * lock count by dropping the top 32 bits.
4831 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4832 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4833 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4834 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4835 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4838 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4839 #endif /* HAVE_LONGLONG */
4845 #if !defined(HAVE_LONGLONG)
4846 /****************************************************************************
4847 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4848 ****************************************************************************/
4850 static uint32 map_lock_offset(uint32 high, uint32 low)
4854 uint32 highcopy = high;
4857 * Try and find out how many significant bits there are in high.
4860 for(i = 0; highcopy; i++)
4864 * We use 31 bits not 32 here as POSIX
4865 * lock offsets may not be negative.
4868 mask = (~0) << (31 - i);
4871 return 0; /* Fail. */
4877 #endif /* !defined(HAVE_LONGLONG) */
4879 /****************************************************************************
4880 Get a lock offset, dealing with large offset requests.
4881 ****************************************************************************/
4883 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4885 SMB_BIG_UINT offset = 0;
4889 if(!large_file_format) {
4890 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4893 #if defined(HAVE_LONGLONG)
4894 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4895 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4896 #else /* HAVE_LONGLONG */
4899 * NT4.x seems to be broken in that it sends large file (64 bit)
4900 * lockingX calls even if the CAP_LARGE_FILES was *not*
4901 * negotiated. For boxes without large unsigned ints mangle the
4902 * lock offset by mapping the top 32 bits onto the lower 32.
4905 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4906 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4907 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4910 if((new_low = map_lock_offset(high, low)) == 0) {
4912 return (SMB_BIG_UINT)-1;
4915 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4916 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4917 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4918 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4921 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4922 #endif /* HAVE_LONGLONG */
4928 /****************************************************************************
4929 Reply to a lockingX request.
4930 ****************************************************************************/
4932 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4934 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4935 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4936 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4937 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4938 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4939 SMB_BIG_UINT count = 0, offset = 0;
4941 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4944 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4946 BOOL my_lock_ctx = False;
4949 START_PROFILE(SMBlockingX);
4951 CHECK_FSP(fsp,conn);
4953 data = smb_buf(inbuf);
4955 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4956 /* we don't support these - and CANCEL_LOCK makes w2k
4957 and XP reboot so I don't really want to be
4958 compatible! (tridge) */
4959 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4962 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4963 /* Need to make this like a cancel.... JRA. */
4964 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4967 /* Check if this is an oplock break on a file
4968 we have granted an oplock on.
4970 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4971 /* Client can insist on breaking to none. */
4972 BOOL break_to_none = (oplocklevel == 0);
4974 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4975 (unsigned int)oplocklevel, fsp->fnum ));
4978 * Make sure we have granted an exclusive or batch oplock on this file.
4981 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4982 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4983 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4985 /* if this is a pure oplock break request then don't send a reply */
4986 if (num_locks == 0 && num_ulocks == 0) {
4987 END_PROFILE(SMBlockingX);
4990 END_PROFILE(SMBlockingX);
4991 return ERROR_DOS(ERRDOS,ERRlock);
4995 if (remove_oplock(fsp, break_to_none) == False) {
4996 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
5000 /* if this is a pure oplock break request then don't send a reply */
5001 if (num_locks == 0 && num_ulocks == 0) {
5002 /* Sanity check - ensure a pure oplock break is not a
5004 if(CVAL(inbuf,smb_vwv0) != 0xff)
5005 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
5006 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5007 END_PROFILE(SMBlockingX);
5013 * We do this check *after* we have checked this is not a oplock break
5014 * response message. JRA.
5017 release_level_2_oplocks_on_change(fsp);
5019 /* Data now points at the beginning of the list
5020 of smb_unlkrng structs */
5021 for(i = 0; i < (int)num_ulocks; i++) {
5022 lock_pid = get_lock_pid( data, i, large_file_format);
5023 count = get_lock_count( data, i, large_file_format);
5024 offset = get_lock_offset( data, i, large_file_format, &err);
5027 * There is no error code marked "stupid client bug".... :-).
5030 END_PROFILE(SMBlockingX);
5031 return ERROR_DOS(ERRDOS,ERRnoaccess);
5034 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
5035 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
5037 status = do_unlock(fsp,conn,lock_pid,count,offset);
5038 if (NT_STATUS_V(status)) {
5039 END_PROFILE(SMBlockingX);
5040 return ERROR_NT(status);
5044 /* Setup the timeout in seconds. */
5046 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5048 /* Now do any requested locks */
5049 data += ((large_file_format ? 20 : 10)*num_ulocks);
5051 /* Data now points at the beginning of the list
5052 of smb_lkrng structs */
5054 for(i = 0; i < (int)num_locks; i++) {
5055 lock_pid = get_lock_pid( data, i, large_file_format);
5056 count = get_lock_count( data, i, large_file_format);
5057 offset = get_lock_offset( data, i, large_file_format, &err);
5060 * There is no error code marked "stupid client bug".... :-).
5063 END_PROFILE(SMBlockingX);
5064 return ERROR_DOS(ERRDOS,ERRnoaccess);
5067 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
5068 (double)offset, (double)count, (unsigned int)lock_pid,
5069 fsp->fsp_name, (int)lock_timeout ));
5071 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
5072 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
5073 if (NT_STATUS_V(status)) {
5075 * Interesting fact found by IFSTEST /t LockOverlappedTest...
5076 * Even if it's our own lock context, we need to wait here as
5077 * there may be an unlock on the way.
5078 * So I removed a "&& !my_lock_ctx" from the following
5079 * if statement. JRA.
5081 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
5083 * A blocking lock was requested. Package up
5084 * this smb into a queued request and push it
5085 * onto the blocking lock queue.
5087 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
5088 END_PROFILE(SMBlockingX);
5096 /* If any of the above locks failed, then we must unlock
5097 all of the previous locks (X/Open spec). */
5098 if (i != num_locks && num_locks != 0) {
5100 * Ensure we don't do a remove on the lock that just failed,
5101 * as under POSIX rules, if we have a lock already there, we
5102 * will delete it (and we shouldn't) .....
5104 for(i--; i >= 0; i--) {
5105 lock_pid = get_lock_pid( data, i, large_file_format);
5106 count = get_lock_count( data, i, large_file_format);
5107 offset = get_lock_offset( data, i, large_file_format, &err);
5110 * There is no error code marked "stupid client bug".... :-).
5113 END_PROFILE(SMBlockingX);
5114 return ERROR_DOS(ERRDOS,ERRnoaccess);
5117 do_unlock(fsp,conn,lock_pid,count,offset);
5119 END_PROFILE(SMBlockingX);
5120 return ERROR_NT(status);
5123 set_message(outbuf,2,0,True);
5125 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5126 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5128 END_PROFILE(SMBlockingX);
5129 return chain_reply(inbuf,outbuf,length,bufsize);
5133 #define DBGC_CLASS DBGC_ALL
5135 /****************************************************************************
5136 Reply to a SMBreadbmpx (read block multiplex) request.
5137 ****************************************************************************/
5139 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5150 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5151 START_PROFILE(SMBreadBmpx);
5153 /* this function doesn't seem to work - disable by default */
5154 if (!lp_readbmpx()) {
5155 END_PROFILE(SMBreadBmpx);
5156 return ERROR_DOS(ERRSRV,ERRuseSTD);
5159 outsize = set_message(outbuf,8,0,True);
5161 CHECK_FSP(fsp,conn);
5164 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5165 maxcount = SVAL(inbuf,smb_vwv3);
5167 data = smb_buf(outbuf);
5168 pad = ((long)data)%4;
5173 max_per_packet = bufsize-(outsize+pad);
5177 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5178 END_PROFILE(SMBreadBmpx);
5179 return ERROR_DOS(ERRDOS,ERRlock);
5183 size_t N = MIN(max_per_packet,tcount-total_read);
5185 nread = read_file(fsp,data,startpos,N);
5190 if (nread < (ssize_t)N)
5191 tcount = total_read + nread;
5193 set_message(outbuf,8,nread,False);
5194 SIVAL(outbuf,smb_vwv0,startpos);
5195 SSVAL(outbuf,smb_vwv2,tcount);
5196 SSVAL(outbuf,smb_vwv6,nread);
5197 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5200 if (!send_smb(smbd_server_fd(),outbuf))
5201 exit_server("reply_readbmpx: send_smb failed.");
5203 total_read += nread;
5205 } while (total_read < (ssize_t)tcount);
5207 END_PROFILE(SMBreadBmpx);
5211 /****************************************************************************
5212 Reply to a SMBsetattrE.
5213 ****************************************************************************/
5215 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5217 struct utimbuf unix_times;
5219 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5220 START_PROFILE(SMBsetattrE);
5222 outsize = set_message(outbuf,0,0,True);
5224 if(!fsp || (fsp->conn != conn)) {
5225 END_PROFILE(SMBgetattrE);
5226 return ERROR_DOS(ERRDOS,ERRbadfid);
5230 * Convert the DOS times into unix times. Ignore create
5231 * time as UNIX can't set this.
5234 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5235 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5238 * Patch from Ray Frush <frush@engr.colostate.edu>
5239 * Sometimes times are sent as zero - ignore them.
5242 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5243 /* Ignore request */
5244 if( DEBUGLVL( 3 ) ) {
5245 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5246 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5248 END_PROFILE(SMBsetattrE);
5250 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5251 /* set modify time = to access time if modify time was unset */
5252 unix_times.modtime = unix_times.actime;
5255 /* Set the date on this file */
5256 /* Should we set pending modtime here ? JRA */
5257 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5258 END_PROFILE(SMBsetattrE);
5259 return ERROR_DOS(ERRDOS,ERRnoaccess);
5262 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5263 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5265 END_PROFILE(SMBsetattrE);
5270 /* Back from the dead for OS/2..... JRA. */
5272 /****************************************************************************
5273 Reply to a SMBwritebmpx (write block multiplex primary) request.
5274 ****************************************************************************/
5276 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5279 ssize_t nwritten = -1;
5286 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5287 START_PROFILE(SMBwriteBmpx);
5289 CHECK_FSP(fsp,conn);
5291 if (HAS_CACHED_ERROR(fsp)) {
5292 return(CACHED_ERROR(fsp));
5295 tcount = SVAL(inbuf,smb_vwv1);
5296 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5297 write_through = BITSETW(inbuf+smb_vwv7,0);
5298 numtowrite = SVAL(inbuf,smb_vwv10);
5299 smb_doff = SVAL(inbuf,smb_vwv11);
5301 data = smb_base(inbuf) + smb_doff;
5303 /* If this fails we need to send an SMBwriteC response,
5304 not an SMBwritebmpx - set this up now so we don't forget */
5305 SCVAL(outbuf,smb_com,SMBwritec);
5307 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5308 END_PROFILE(SMBwriteBmpx);
5309 return(ERROR_DOS(ERRDOS,ERRlock));
5312 nwritten = write_file(fsp,data,startpos,numtowrite);
5314 if(lp_syncalways(SNUM(conn)) || write_through)
5315 sync_file(conn,fsp);
5317 if(nwritten < (ssize_t)numtowrite) {
5318 END_PROFILE(SMBwriteBmpx);
5319 return(UNIXERROR(ERRHRD,ERRdiskfull));
5322 /* If the maximum to be written to this file
5323 is greater than what we just wrote then set
5324 up a secondary struct to be attached to this
5325 fd, we will use this to cache error messages etc. */
5327 if((ssize_t)tcount > nwritten) {
5328 write_bmpx_struct *wbms;
5329 if(fsp->wbmpx_ptr != NULL)
5330 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5332 wbms = SMB_MALLOC_P(write_bmpx_struct);
5334 DEBUG(0,("Out of memory in reply_readmpx\n"));
5335 END_PROFILE(SMBwriteBmpx);
5336 return(ERROR_DOS(ERRSRV,ERRnoresource));
5338 wbms->wr_mode = write_through;
5339 wbms->wr_discard = False; /* No errors yet */
5340 wbms->wr_total_written = nwritten;
5341 wbms->wr_errclass = 0;
5343 fsp->wbmpx_ptr = wbms;
5346 /* We are returning successfully, set the message type back to
5348 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5350 outsize = set_message(outbuf,1,0,True);
5352 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5354 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5355 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5357 if (write_through && tcount==nwritten) {
5358 /* We need to send both a primary and a secondary response */
5359 smb_setlen(outbuf,outsize - 4);
5361 if (!send_smb(smbd_server_fd(),outbuf))
5362 exit_server("reply_writebmpx: send_smb failed.");
5364 /* Now the secondary */
5365 outsize = set_message(outbuf,1,0,True);
5366 SCVAL(outbuf,smb_com,SMBwritec);
5367 SSVAL(outbuf,smb_vwv0,nwritten);
5370 END_PROFILE(SMBwriteBmpx);
5374 /****************************************************************************
5375 Reply to a SMBwritebs (write block multiplex secondary) request.
5376 ****************************************************************************/
5378 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5381 ssize_t nwritten = -1;
5388 write_bmpx_struct *wbms;
5389 BOOL send_response = False;
5390 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5391 START_PROFILE(SMBwriteBs);
5393 CHECK_FSP(fsp,conn);
5396 tcount = SVAL(inbuf,smb_vwv1);
5397 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5398 numtowrite = SVAL(inbuf,smb_vwv6);
5399 smb_doff = SVAL(inbuf,smb_vwv7);
5401 data = smb_base(inbuf) + smb_doff;
5403 /* We need to send an SMBwriteC response, not an SMBwritebs */
5404 SCVAL(outbuf,smb_com,SMBwritec);
5406 /* This fd should have an auxiliary struct attached,
5407 check that it does */
5408 wbms = fsp->wbmpx_ptr;
5410 END_PROFILE(SMBwriteBs);
5414 /* If write through is set we can return errors, else we must cache them */
5415 write_through = wbms->wr_mode;
5417 /* Check for an earlier error */
5418 if(wbms->wr_discard) {
5419 END_PROFILE(SMBwriteBs);
5420 return -1; /* Just discard the packet */
5423 nwritten = write_file(fsp,data,startpos,numtowrite);
5425 if(lp_syncalways(SNUM(conn)) || write_through)
5426 sync_file(conn,fsp);
5428 if (nwritten < (ssize_t)numtowrite) {
5430 /* We are returning an error - we can delete the aux struct */
5433 fsp->wbmpx_ptr = NULL;
5434 END_PROFILE(SMBwriteBs);
5435 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5437 wbms->wr_errclass = ERRHRD;
5438 wbms->wr_error = ERRdiskfull;
5439 wbms->wr_status = NT_STATUS_DISK_FULL;
5440 wbms->wr_discard = True;
5441 END_PROFILE(SMBwriteBs);
5445 /* Increment the total written, if this matches tcount
5446 we can discard the auxiliary struct (hurrah !) and return a writeC */
5447 wbms->wr_total_written += nwritten;
5448 if(wbms->wr_total_written >= tcount) {
5449 if (write_through) {
5450 outsize = set_message(outbuf,1,0,True);
5451 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5452 send_response = True;
5456 fsp->wbmpx_ptr = NULL;
5460 END_PROFILE(SMBwriteBs);
5464 END_PROFILE(SMBwriteBs);
5468 /****************************************************************************
5469 Reply to a SMBgetattrE.
5470 ****************************************************************************/
5472 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5474 SMB_STRUCT_STAT sbuf;
5477 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5478 START_PROFILE(SMBgetattrE);
5480 outsize = set_message(outbuf,11,0,True);
5482 if(!fsp || (fsp->conn != conn)) {
5483 END_PROFILE(SMBgetattrE);
5484 return ERROR_DOS(ERRDOS,ERRbadfid);
5487 /* Do an fstat on this file */
5488 if(fsp_stat(fsp, &sbuf)) {
5489 END_PROFILE(SMBgetattrE);
5490 return(UNIXERROR(ERRDOS,ERRnoaccess));
5493 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5496 * Convert the times into dos times. Set create
5497 * date to be last modify date as UNIX doesn't save
5501 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5502 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5503 /* Should we check pending modtime here ? JRA */
5504 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5507 SIVAL(outbuf,smb_vwv6,0);
5508 SIVAL(outbuf,smb_vwv8,0);
5510 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5511 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5512 SIVAL(outbuf,smb_vwv8,allocation_size);
5514 SSVAL(outbuf,smb_vwv10, mode);
5516 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5518 END_PROFILE(SMBgetattrE);