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-2007.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
33 unsigned int smb_echo_count = 0;
34 extern uint32 global_client_caps;
36 extern struct current_user current_user;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41 path or anything including wildcards.
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_internal(pstring destname,
48 const pstring srcname,
50 BOOL *p_last_component_contains_wcard)
53 const char *s = srcname;
54 NTSTATUS ret = NT_STATUS_OK;
55 BOOL start_of_name_component = True;
57 *p_last_component_contains_wcard = False;
60 if (IS_DIRECTORY_SEP(*s)) {
62 * Safe to assume is not the second part of a mb char
63 * as this is handled below.
65 /* Eat multiple '/' or '\\' */
66 while (IS_DIRECTORY_SEP(*s)) {
69 if ((d != destname) && (*s != '\0')) {
70 /* We only care about non-leading or trailing '/' or '\\' */
74 start_of_name_component = True;
76 *p_last_component_contains_wcard = False;
80 if (start_of_name_component) {
81 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
82 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
85 * No mb char starts with '.' so we're safe checking the directory separator here.
88 /* If we just added a '/' - delete it */
89 if ((d > destname) && (*(d-1) == '/')) {
94 /* Are we at the start ? Can't go back further if so. */
96 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
99 /* Go back one level... */
100 /* We know this is safe as '/' cannot be part of a mb sequence. */
101 /* NOTE - if this assumption is invalid we are not in good shape... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d--; d > destname; d--) {
107 s += 2; /* Else go past the .. */
108 /* We're still at the start of a name component, just the previous one. */
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
124 return NT_STATUS_OBJECT_NAME_INVALID;
132 *p_last_component_contains_wcard = True;
141 /* Get the size of the next MB character. */
142 next_codepoint(s,&siz);
160 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162 return NT_STATUS_INVALID_PARAMETER;
165 start_of_name_component = False;
172 /****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175 ****************************************************************************/
177 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
180 return check_path_syntax_internal(destname, srcname, True, &ignore);
183 /****************************************************************************
184 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
185 Wildcards allowed - p_contains_wcard returns true if the last component contained
187 ****************************************************************************/
189 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
191 return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
194 /****************************************************************************
195 Check the path for a POSIX client.
196 We're assuming here that '/' is not the second byte in any multibyte char
197 set (a safe assumption).
198 ****************************************************************************/
200 static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
203 return check_path_syntax_internal(destname, srcname, False, &ignore);
206 /****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208 ****************************************************************************/
210 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
211 NTSTATUS *err, BOOL *contains_wcard)
214 char *tmppath_ptr = tmppath;
217 SMB_ASSERT(dest_len == sizeof(pstring));
221 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
223 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
226 *contains_wcard = False;
228 if (lp_posix_pathnames()) {
229 *err = check_path_syntax_posix(dest, tmppath);
231 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
237 /****************************************************************************
238 Pull a string and check the path - provide for error return.
239 ****************************************************************************/
241 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
244 char *tmppath_ptr = tmppath;
247 SMB_ASSERT(dest_len == sizeof(pstring));
251 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
253 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
255 if (lp_posix_pathnames()) {
256 *err = check_path_syntax_posix(dest, tmppath);
258 *err = check_path_syntax(dest, tmppath);
264 /****************************************************************************
265 Reply to a special message.
266 ****************************************************************************/
268 int reply_special(char *inbuf,char *outbuf)
271 int msg_type = CVAL(inbuf,0);
272 int msg_flags = CVAL(inbuf,1);
276 static BOOL already_got_session = False;
280 memset(outbuf,'\0',smb_size);
282 smb_setlen(outbuf,0);
285 case 0x81: /* session request */
287 if (already_got_session) {
288 exit_server_cleanly("multiple session request not permitted");
291 SCVAL(outbuf,0,0x82);
293 if (name_len(inbuf+4) > 50 ||
294 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
295 DEBUG(0,("Invalid name length in session request\n"));
298 name_extract(inbuf,4,name1);
299 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
300 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
303 set_local_machine_name(name1, True);
304 set_remote_machine_name(name2, True);
306 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
307 get_local_machine_name(), get_remote_machine_name(),
310 if (name_type == 'R') {
311 /* We are being asked for a pathworks session ---
313 SCVAL(outbuf, 0,0x83);
317 /* only add the client's machine name to the list
318 of possibly valid usernames if we are operating
319 in share mode security */
320 if (lp_security() == SEC_SHARE) {
321 add_session_user(get_remote_machine_name());
324 reload_services(True);
327 already_got_session = True;
330 case 0x89: /* session keepalive request
331 (some old clients produce this?) */
332 SCVAL(outbuf,0,SMBkeepalive);
336 case 0x82: /* positive session response */
337 case 0x83: /* negative session response */
338 case 0x84: /* retarget session response */
339 DEBUG(0,("Unexpected session response\n"));
342 case SMBkeepalive: /* session keepalive */
347 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
348 msg_type, msg_flags));
353 /****************************************************************************
355 conn POINTER CAN BE NULL HERE !
356 ****************************************************************************/
358 int reply_tcon(connection_struct *conn,
359 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
366 uint16 vuid = SVAL(inbuf,smb_uid);
370 DATA_BLOB password_blob;
372 START_PROFILE(SMBtcon);
374 *service_buf = *password = *dev = 0;
376 p = smb_buf(inbuf)+1;
377 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
378 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
380 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
382 p = strrchr_m(service_buf,'\\');
386 service = service_buf;
389 password_blob = data_blob(password, pwlen+1);
391 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
393 data_blob_clear_free(&password_blob);
396 END_PROFILE(SMBtcon);
397 return ERROR_NT(nt_status);
400 outsize = set_message(outbuf,2,0,True);
401 SSVAL(outbuf,smb_vwv0,max_recv);
402 SSVAL(outbuf,smb_vwv1,conn->cnum);
403 SSVAL(outbuf,smb_tid,conn->cnum);
405 DEBUG(3,("tcon service=%s cnum=%d\n",
406 service, conn->cnum));
408 END_PROFILE(SMBtcon);
412 /****************************************************************************
413 Reply to a tcon and X.
414 conn POINTER CAN BE NULL HERE !
415 ****************************************************************************/
417 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
422 /* what the cleint thinks the device is */
423 fstring client_devicetype;
424 /* what the server tells the client the share represents */
425 const char *server_devicetype;
427 uint16 vuid = SVAL(inbuf,smb_uid);
428 int passlen = SVAL(inbuf,smb_vwv3);
432 START_PROFILE(SMBtconX);
434 *service = *client_devicetype = 0;
436 /* we might have to close an old one */
437 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
438 close_cnum(conn,vuid);
441 if (passlen > MAX_PASS_LEN) {
442 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
445 if (global_encrypted_passwords_negotiated) {
446 password = data_blob(smb_buf(inbuf),passlen);
448 password = data_blob(smb_buf(inbuf),passlen+1);
449 /* Ensure correct termination */
450 password.data[passlen]=0;
453 p = smb_buf(inbuf) + passlen;
454 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
457 * the service name can be either: \\server\share
458 * or share directly like on the DELL PowerVault 705
461 q = strchr_m(path+2,'\\');
463 END_PROFILE(SMBtconX);
464 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
466 fstrcpy(service,q+1);
469 fstrcpy(service,path);
471 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
473 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
475 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
477 data_blob_clear_free(&password);
480 END_PROFILE(SMBtconX);
481 return ERROR_NT(nt_status);
485 server_devicetype = "IPC";
486 else if ( IS_PRINT(conn) )
487 server_devicetype = "LPT1:";
489 server_devicetype = "A:";
491 if (Protocol < PROTOCOL_NT1) {
492 set_message(outbuf,2,0,True);
494 p += srvstr_push(outbuf, p, server_devicetype, -1,
495 STR_TERMINATE|STR_ASCII);
496 set_message_end(outbuf,p);
498 /* NT sets the fstype of IPC$ to the null string */
499 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
501 set_message(outbuf,3,0,True);
504 p += srvstr_push(outbuf, p, server_devicetype, -1,
505 STR_TERMINATE|STR_ASCII);
506 p += srvstr_push(outbuf, p, fstype, -1,
509 set_message_end(outbuf,p);
511 /* what does setting this bit do? It is set by NT4 and
512 may affect the ability to autorun mounted cdroms */
513 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
514 (lp_csc_policy(SNUM(conn)) << 2));
516 init_dfsroot(conn, inbuf, outbuf);
520 DEBUG(3,("tconX service=%s \n",
523 /* set the incoming and outgoing tid to the just created one */
524 SSVAL(inbuf,smb_tid,conn->cnum);
525 SSVAL(outbuf,smb_tid,conn->cnum);
527 END_PROFILE(SMBtconX);
528 return chain_reply(inbuf,outbuf,length,bufsize);
531 /****************************************************************************
532 Reply to an unknown type.
533 ****************************************************************************/
535 int reply_unknown(char *inbuf,char *outbuf)
538 type = CVAL(inbuf,smb_com);
540 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
541 smb_fn_name(type), type, type));
543 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
546 /****************************************************************************
548 conn POINTER CAN BE NULL HERE !
549 ****************************************************************************/
551 int reply_ioctl(connection_struct *conn,
552 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
554 uint16 device = SVAL(inbuf,smb_vwv1);
555 uint16 function = SVAL(inbuf,smb_vwv2);
556 uint32 ioctl_code = (device << 16) + function;
557 int replysize, outsize;
559 START_PROFILE(SMBioctl);
561 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
563 switch (ioctl_code) {
564 case IOCTL_QUERY_JOB_INFO:
568 END_PROFILE(SMBioctl);
569 return(ERROR_DOS(ERRSRV,ERRnosupport));
572 outsize = set_message(outbuf,8,replysize+1,True);
573 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
574 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
575 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
576 p = smb_buf(outbuf) + 1; /* Allow for alignment */
578 switch (ioctl_code) {
579 case IOCTL_QUERY_JOB_INFO:
581 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
583 END_PROFILE(SMBioctl);
584 return(UNIXERROR(ERRDOS,ERRbadfid));
586 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
587 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
589 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
595 END_PROFILE(SMBioctl);
599 /****************************************************************************
600 Strange checkpath NTSTATUS mapping.
601 ****************************************************************************/
603 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
605 /* Strange DOS error code semantics only for checkpath... */
606 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
607 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
608 /* We need to map to ERRbadpath */
609 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
615 /****************************************************************************
616 Reply to a checkpath.
617 ****************************************************************************/
619 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
623 SMB_STRUCT_STAT sbuf;
626 START_PROFILE(SMBcheckpath);
628 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
629 if (!NT_STATUS_IS_OK(status)) {
630 END_PROFILE(SMBcheckpath);
631 status = map_checkpath_error(inbuf, status);
632 return ERROR_NT(status);
635 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
637 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
639 status = unix_convert(conn, name, False, NULL, &sbuf);
640 if (!NT_STATUS_IS_OK(status)) {
644 status = check_name(conn, name);
645 if (!NT_STATUS_IS_OK(status)) {
646 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
650 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
651 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
652 status = map_nt_error_from_unix(errno);
656 if (!S_ISDIR(sbuf.st_mode)) {
657 END_PROFILE(SMBcheckpath);
658 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
661 outsize = set_message(outbuf,0,0,False);
663 END_PROFILE(SMBcheckpath);
668 END_PROFILE(SMBcheckpath);
670 /* We special case this - as when a Windows machine
671 is parsing a path is steps through the components
672 one at a time - if a component fails it expects
673 ERRbadpath, not ERRbadfile.
675 status = map_checkpath_error(inbuf, status);
676 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
678 * Windows returns different error codes if
679 * the parent directory is valid but not the
680 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
681 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
682 * if the path is invalid.
684 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
687 return ERROR_NT(status);
690 /****************************************************************************
692 ****************************************************************************/
694 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
698 SMB_STRUCT_STAT sbuf;
705 START_PROFILE(SMBgetatr);
707 p = smb_buf(inbuf) + 1;
708 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
709 if (!NT_STATUS_IS_OK(status)) {
710 END_PROFILE(SMBgetatr);
711 return ERROR_NT(status);
714 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
716 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
717 under WfWg - weird! */
718 if (*fname == '\0') {
719 mode = aHIDDEN | aDIR;
720 if (!CAN_WRITE(conn)) {
726 status = unix_convert(conn, fname, False, NULL,&sbuf);
727 if (!NT_STATUS_IS_OK(status)) {
728 END_PROFILE(SMBgetatr);
729 return ERROR_NT(status);
731 status = check_name(conn, fname);
732 if (!NT_STATUS_IS_OK(status)) {
733 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
734 END_PROFILE(SMBgetatr);
735 return ERROR_NT(status);
737 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
738 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
739 return UNIXERROR(ERRDOS,ERRbadfile);
742 mode = dos_mode(conn,fname,&sbuf);
744 mtime = sbuf.st_mtime;
750 outsize = set_message(outbuf,10,0,True);
752 SSVAL(outbuf,smb_vwv0,mode);
753 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
754 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
756 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
758 SIVAL(outbuf,smb_vwv3,(uint32)size);
760 if (Protocol >= PROTOCOL_NT1) {
761 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
764 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
766 END_PROFILE(SMBgetatr);
770 /****************************************************************************
772 ****************************************************************************/
774 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
780 SMB_STRUCT_STAT sbuf;
784 START_PROFILE(SMBsetatr);
786 p = smb_buf(inbuf) + 1;
787 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
788 if (!NT_STATUS_IS_OK(status)) {
789 END_PROFILE(SMBsetatr);
790 return ERROR_NT(status);
793 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
795 status = unix_convert(conn, fname, False, NULL, &sbuf);
796 if (!NT_STATUS_IS_OK(status)) {
797 END_PROFILE(SMBsetatr);
798 return ERROR_NT(status);
801 if (fname[0] == '.' && fname[1] == '\0') {
803 * Not sure here is the right place to catch this
804 * condition. Might be moved to somewhere else later -- vl
806 END_PROFILE(SMBsetatr);
807 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
810 status = check_name(conn, fname);
811 if (!NT_STATUS_IS_OK(status)) {
812 END_PROFILE(SMBsetatr);
813 return ERROR_NT(status);
816 mode = SVAL(inbuf,smb_vwv0);
817 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
819 if (mode != FILE_ATTRIBUTE_NORMAL) {
820 if (VALID_STAT_OF_DIR(sbuf))
825 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
826 END_PROFILE(SMBsetatr);
827 return UNIXERROR(ERRDOS, ERRnoaccess);
831 if (!set_filetime(conn,fname,mtime)) {
832 END_PROFILE(SMBsetatr);
833 return UNIXERROR(ERRDOS, ERRnoaccess);
836 outsize = set_message(outbuf,0,0,False);
838 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
840 END_PROFILE(SMBsetatr);
844 /****************************************************************************
846 ****************************************************************************/
848 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
851 SMB_BIG_UINT dfree,dsize,bsize;
852 START_PROFILE(SMBdskattr);
854 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
855 END_PROFILE(SMBdskattr);
856 return(UNIXERROR(ERRHRD,ERRgeneral));
859 outsize = set_message(outbuf,5,0,True);
861 if (Protocol <= PROTOCOL_LANMAN2) {
862 double total_space, free_space;
863 /* we need to scale this to a number that DOS6 can handle. We
864 use floating point so we can handle large drives on systems
865 that don't have 64 bit integers
867 we end up displaying a maximum of 2G to DOS systems
869 total_space = dsize * (double)bsize;
870 free_space = dfree * (double)bsize;
872 dsize = (total_space+63*512) / (64*512);
873 dfree = (free_space+63*512) / (64*512);
875 if (dsize > 0xFFFF) dsize = 0xFFFF;
876 if (dfree > 0xFFFF) dfree = 0xFFFF;
878 SSVAL(outbuf,smb_vwv0,dsize);
879 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
880 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
881 SSVAL(outbuf,smb_vwv3,dfree);
883 SSVAL(outbuf,smb_vwv0,dsize);
884 SSVAL(outbuf,smb_vwv1,bsize/512);
885 SSVAL(outbuf,smb_vwv2,512);
886 SSVAL(outbuf,smb_vwv3,dfree);
889 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
891 END_PROFILE(SMBdskattr);
895 /****************************************************************************
897 Can be called from SMBsearch, SMBffirst or SMBfunique.
898 ****************************************************************************/
900 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
910 unsigned int numentries = 0;
911 unsigned int maxentries = 0;
912 BOOL finished = False;
918 BOOL check_descend = False;
919 BOOL expect_close = False;
921 BOOL mask_contains_wcard = False;
922 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
924 START_PROFILE(SMBsearch);
926 if (lp_posix_pathnames()) {
927 END_PROFILE(SMBsearch);
928 return reply_unknown(inbuf, outbuf);
931 *mask = *directory = *fname = 0;
933 /* If we were called as SMBffirst then we must expect close. */
934 if(CVAL(inbuf,smb_com) == SMBffirst) {
938 outsize = set_message(outbuf,1,3,True);
939 maxentries = SVAL(inbuf,smb_vwv0);
940 dirtype = SVAL(inbuf,smb_vwv1);
941 p = smb_buf(inbuf) + 1;
942 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
943 if (!NT_STATUS_IS_OK(nt_status)) {
944 END_PROFILE(SMBsearch);
945 return ERROR_NT(nt_status);
948 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
951 status_len = SVAL(p, 0);
954 /* dirtype &= ~aDIR; */
956 if (status_len == 0) {
957 SMB_STRUCT_STAT sbuf;
960 pstrcpy(directory,path);
962 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
963 if (!NT_STATUS_IS_OK(nt_status)) {
964 END_PROFILE(SMBsearch);
965 return ERROR_NT(nt_status);
969 nt_status = check_name(conn, directory);
970 if (!NT_STATUS_IS_OK(nt_status)) {
971 END_PROFILE(SMBsearch);
972 return ERROR_NT(nt_status);
975 p = strrchr_m(dir2,'/');
984 p = strrchr_m(directory,'/');
991 if (strlen(directory) == 0) {
992 pstrcpy(directory,".");
994 memset((char *)status,'\0',21);
995 SCVAL(status,0,(dirtype & 0x1F));
1000 status_dirtype = CVAL(status,0) & 0x1F;
1001 if (status_dirtype != (dirtype & 0x1F)) {
1002 dirtype = status_dirtype;
1005 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1006 if (!conn->dirptr) {
1009 string_set(&conn->dirpath,dptr_path(dptr_num));
1010 pstrcpy(mask, dptr_wcard(dptr_num));
1013 p = smb_buf(outbuf) + 3;
1015 if (status_len == 0) {
1016 nt_status = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype,&dptr_num);
1017 if (!NT_STATUS_IS_OK(nt_status)) {
1018 return ERROR_NT(nt_status);
1021 dirtype = dptr_attr(dptr_num);
1024 DEBUG(4,("dptr_num is %d\n",dptr_num));
1026 if ((dirtype&0x1F) == aVOLID) {
1027 memcpy(p,status,21);
1028 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1029 0,aVOLID,0,!allow_long_path_components);
1030 dptr_fill(p+12,dptr_num);
1031 if (dptr_zero(p+12) && (status_len==0)) {
1036 p += DIR_STRUCT_SIZE;
1039 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1041 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1042 conn->dirpath,lp_dontdescend(SNUM(conn))));
1043 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1044 check_descend = True;
1047 for (i=numentries;(i<maxentries) && !finished;i++) {
1048 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1050 memcpy(p,status,21);
1051 make_dir_struct(p,mask,fname,size, mode,date,
1052 !allow_long_path_components);
1053 if (!dptr_fill(p+12,dptr_num)) {
1057 p += DIR_STRUCT_SIZE;
1064 /* If we were called as SMBffirst with smb_search_id == NULL
1065 and no entries were found then return error and close dirptr
1068 if (numentries == 0) {
1069 dptr_close(&dptr_num);
1070 } else if(expect_close && status_len == 0) {
1071 /* Close the dptr - we know it's gone */
1072 dptr_close(&dptr_num);
1075 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1076 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1077 dptr_close(&dptr_num);
1080 if ((numentries == 0) && !mask_contains_wcard) {
1081 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1084 SSVAL(outbuf,smb_vwv0,numentries);
1085 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1086 SCVAL(smb_buf(outbuf),0,5);
1087 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1089 /* The replies here are never long name. */
1090 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1091 if (!allow_long_path_components) {
1092 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1095 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1096 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1098 outsize += DIR_STRUCT_SIZE*numentries;
1099 smb_setlen(outbuf,outsize - 4);
1101 if ((! *directory) && dptr_path(dptr_num))
1102 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1104 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1105 smb_fn_name(CVAL(inbuf,smb_com)),
1106 mask, directory, dirtype, numentries, maxentries ) );
1108 END_PROFILE(SMBsearch);
1112 /****************************************************************************
1113 Reply to a fclose (stop directory search).
1114 ****************************************************************************/
1116 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1125 BOOL path_contains_wcard = False;
1127 START_PROFILE(SMBfclose);
1129 if (lp_posix_pathnames()) {
1130 END_PROFILE(SMBfclose);
1131 return reply_unknown(inbuf, outbuf);
1134 outsize = set_message(outbuf,1,0,True);
1135 p = smb_buf(inbuf) + 1;
1136 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1137 if (!NT_STATUS_IS_OK(err)) {
1138 END_PROFILE(SMBfclose);
1139 return ERROR_NT(err);
1142 status_len = SVAL(p,0);
1145 if (status_len == 0) {
1146 END_PROFILE(SMBfclose);
1147 return ERROR_DOS(ERRSRV,ERRsrverror);
1150 memcpy(status,p,21);
1152 if(dptr_fetch(status+12,&dptr_num)) {
1153 /* Close the dptr - we know it's gone */
1154 dptr_close(&dptr_num);
1157 SSVAL(outbuf,smb_vwv0,0);
1159 DEBUG(3,("search close\n"));
1161 END_PROFILE(SMBfclose);
1165 /****************************************************************************
1167 ****************************************************************************/
1169 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1177 SMB_STRUCT_STAT sbuf;
1179 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1181 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1184 uint32 create_disposition;
1185 uint32 create_options = 0;
1187 START_PROFILE(SMBopen);
1189 deny_mode = SVAL(inbuf,smb_vwv0);
1191 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1192 if (!NT_STATUS_IS_OK(status)) {
1193 END_PROFILE(SMBopen);
1194 return ERROR_NT(status);
1197 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1199 status = unix_convert(conn, fname, False, NULL, &sbuf);
1200 if (!NT_STATUS_IS_OK(status)) {
1201 END_PROFILE(SMBopen);
1202 return ERROR_NT(status);
1205 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1206 &access_mask, &share_mode, &create_disposition, &create_options)) {
1207 END_PROFILE(SMBopen);
1208 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1211 status = open_file_ntcreate(conn,fname,&sbuf,
1220 if (!NT_STATUS_IS_OK(status)) {
1221 END_PROFILE(SMBopen);
1222 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1223 /* We have re-scheduled this call. */
1226 return ERROR_NT(status);
1229 size = sbuf.st_size;
1230 fattr = dos_mode(conn,fname,&sbuf);
1231 mtime = sbuf.st_mtime;
1234 DEBUG(3,("attempt to open a directory %s\n",fname));
1235 close_file(fsp,ERROR_CLOSE);
1236 END_PROFILE(SMBopen);
1237 return ERROR_DOS(ERRDOS,ERRnoaccess);
1240 outsize = set_message(outbuf,7,0,True);
1241 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1242 SSVAL(outbuf,smb_vwv1,fattr);
1243 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1244 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1246 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1248 SIVAL(outbuf,smb_vwv4,(uint32)size);
1249 SSVAL(outbuf,smb_vwv6,deny_mode);
1251 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1252 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1255 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1256 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1258 END_PROFILE(SMBopen);
1262 /****************************************************************************
1263 Reply to an open and X.
1264 ****************************************************************************/
1266 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1269 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1270 int deny_mode = SVAL(inbuf,smb_vwv3);
1271 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1272 /* Breakout the oplock request bits so we can set the
1273 reply bits separately. */
1274 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1275 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1276 int oplock_request = ex_oplock_request | core_oplock_request;
1278 int smb_sattr = SVAL(inbuf,smb_vwv4);
1279 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1281 int smb_ofun = SVAL(inbuf,smb_vwv8);
1284 SMB_STRUCT_STAT sbuf;
1288 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1289 ssize_t retval = -1;
1292 uint32 create_disposition;
1293 uint32 create_options = 0;
1295 START_PROFILE(SMBopenX);
1297 /* If it's an IPC, pass off the pipe handler. */
1299 if (lp_nt_pipe_support()) {
1300 END_PROFILE(SMBopenX);
1301 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1303 END_PROFILE(SMBopenX);
1304 return ERROR_DOS(ERRSRV,ERRaccess);
1308 /* XXXX we need to handle passed times, sattr and flags */
1309 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 END_PROFILE(SMBopenX);
1312 return ERROR_NT(status);
1315 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1317 status = unix_convert(conn, fname, False, NULL, &sbuf);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 END_PROFILE(SMBopenX);
1320 return ERROR_NT(status);
1323 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1326 &create_disposition,
1328 END_PROFILE(SMBopenX);
1329 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1332 status = open_file_ntcreate(conn,fname,&sbuf,
1341 if (!NT_STATUS_IS_OK(status)) {
1342 END_PROFILE(SMBopenX);
1343 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1344 /* We have re-scheduled this call. */
1347 return ERROR_NT(status);
1350 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1351 if the file is truncated or created. */
1352 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1353 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1354 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1355 close_file(fsp,ERROR_CLOSE);
1356 END_PROFILE(SMBopenX);
1357 return ERROR_NT(NT_STATUS_DISK_FULL);
1359 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1361 close_file(fsp,ERROR_CLOSE);
1362 END_PROFILE(SMBopenX);
1363 return ERROR_NT(NT_STATUS_DISK_FULL);
1365 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1368 fattr = dos_mode(conn,fname,&sbuf);
1369 mtime = sbuf.st_mtime;
1371 close_file(fsp,ERROR_CLOSE);
1372 END_PROFILE(SMBopenX);
1373 return ERROR_DOS(ERRDOS,ERRnoaccess);
1376 /* If the caller set the extended oplock request bit
1377 and we granted one (by whatever means) - set the
1378 correct bit for extended oplock reply.
1381 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1382 smb_action |= EXTENDED_OPLOCK_GRANTED;
1385 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1386 smb_action |= EXTENDED_OPLOCK_GRANTED;
1389 /* If the caller set the core oplock request bit
1390 and we granted one (by whatever means) - set the
1391 correct bit for core oplock reply.
1394 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1395 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1398 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1399 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1402 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1403 set_message(outbuf,19,0,True);
1405 set_message(outbuf,15,0,True);
1407 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1408 SSVAL(outbuf,smb_vwv3,fattr);
1409 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1410 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1412 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1414 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1415 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1416 SSVAL(outbuf,smb_vwv11,smb_action);
1418 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1419 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1422 END_PROFILE(SMBopenX);
1423 return chain_reply(inbuf,outbuf,length,bufsize);
1426 /****************************************************************************
1427 Reply to a SMBulogoffX.
1428 conn POINTER CAN BE NULL HERE !
1429 ****************************************************************************/
1431 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1433 uint16 vuid = SVAL(inbuf,smb_uid);
1434 user_struct *vuser = get_valid_user_struct(vuid);
1435 START_PROFILE(SMBulogoffX);
1438 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1440 /* in user level security we are supposed to close any files
1441 open by this user */
1442 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1443 file_close_user(vuid);
1445 invalidate_vuid(vuid);
1447 set_message(outbuf,2,0,True);
1449 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1451 END_PROFILE(SMBulogoffX);
1452 return chain_reply(inbuf,outbuf,length,bufsize);
1455 /****************************************************************************
1456 Reply to a mknew or a create.
1457 ****************************************************************************/
1459 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1464 uint32 fattr = SVAL(inbuf,smb_vwv0);
1465 struct utimbuf times;
1467 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1468 SMB_STRUCT_STAT sbuf;
1470 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1471 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1472 uint32 create_disposition;
1473 uint32 create_options = 0;
1475 START_PROFILE(SMBcreate);
1477 com = SVAL(inbuf,smb_com);
1479 times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
1481 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 END_PROFILE(SMBcreate);
1484 return ERROR_NT(status);
1487 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1489 status = unix_convert(conn, fname, False, NULL, &sbuf);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 END_PROFILE(SMBcreate);
1492 return ERROR_NT(status);
1495 if (fattr & aVOLID) {
1496 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1499 if(com == SMBmknew) {
1500 /* We should fail if file exists. */
1501 create_disposition = FILE_CREATE;
1503 /* Create if file doesn't exist, truncate if it does. */
1504 create_disposition = FILE_OVERWRITE_IF;
1507 /* Open file using ntcreate. */
1508 status = open_file_ntcreate(conn,fname,&sbuf,
1517 if (!NT_STATUS_IS_OK(status)) {
1518 END_PROFILE(SMBcreate);
1519 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1520 /* We have re-scheduled this call. */
1523 return ERROR_NT(status);
1526 times.actime = sbuf.st_atime;
1527 file_utime(conn, fname, ×);
1529 outsize = set_message(outbuf,1,0,True);
1530 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1532 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1533 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1536 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1537 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1540 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1541 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1543 END_PROFILE(SMBcreate);
1547 /****************************************************************************
1548 Reply to a create temporary file.
1549 ****************************************************************************/
1551 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1555 uint32 fattr = SVAL(inbuf,smb_vwv0);
1557 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1559 SMB_STRUCT_STAT sbuf;
1562 unsigned int namelen;
1564 START_PROFILE(SMBctemp);
1566 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 END_PROFILE(SMBctemp);
1569 return ERROR_NT(status);
1572 pstrcat(fname,"/TMXXXXXX");
1574 pstrcat(fname,"TMXXXXXX");
1577 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1579 status = unix_convert(conn, fname, False, NULL, &sbuf);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 END_PROFILE(SMBctemp);
1582 return ERROR_NT(status);
1585 tmpfd = smb_mkstemp(fname);
1587 END_PROFILE(SMBctemp);
1588 return(UNIXERROR(ERRDOS,ERRnoaccess));
1591 SMB_VFS_STAT(conn,fname,&sbuf);
1593 /* We should fail if file does not exist. */
1594 status = open_file_ntcreate(conn,fname,&sbuf,
1595 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1596 FILE_SHARE_READ|FILE_SHARE_WRITE,
1603 /* close fd from smb_mkstemp() */
1606 if (!NT_STATUS_IS_OK(status)) {
1607 END_PROFILE(SMBctemp);
1608 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1609 /* We have re-scheduled this call. */
1612 return ERROR_NT(status);
1615 outsize = set_message(outbuf,1,0,True);
1616 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1618 /* the returned filename is relative to the directory */
1619 s = strrchr_m(fname, '/');
1626 p = smb_buf(outbuf);
1628 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1629 thing in the byte section. JRA */
1630 SSVALS(p, 0, -1); /* what is this? not in spec */
1632 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1634 outsize = set_message_end(outbuf, p);
1636 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1637 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1640 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1641 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1644 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1645 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1646 (unsigned int)sbuf.st_mode ) );
1648 END_PROFILE(SMBctemp);
1652 /*******************************************************************
1653 Check if a user is allowed to rename a file.
1654 ********************************************************************/
1656 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1662 if (!CAN_WRITE(conn)) {
1663 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1666 fmode = dos_mode(conn,fname,pst);
1667 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1668 return NT_STATUS_NO_SUCH_FILE;
1671 if (S_ISDIR(pst->st_mode)) {
1672 return NT_STATUS_OK;
1675 status = open_file_ntcreate(conn, fname, pst,
1677 FILE_SHARE_READ|FILE_SHARE_WRITE,
1680 FILE_ATTRIBUTE_NORMAL,
1684 if (!NT_STATUS_IS_OK(status)) {
1687 close_file(fsp,NORMAL_CLOSE);
1688 return NT_STATUS_OK;
1691 /*******************************************************************
1692 Check if a user is allowed to delete a file.
1693 ********************************************************************/
1695 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1696 uint32 dirtype, BOOL can_defer)
1698 SMB_STRUCT_STAT sbuf;
1701 uint32 dirtype_orig = dirtype;
1704 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1706 if (!CAN_WRITE(conn)) {
1707 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1710 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1711 return map_nt_error_from_unix(errno);
1714 fattr = dos_mode(conn,fname,&sbuf);
1716 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1717 dirtype = aDIR|aARCH|aRONLY;
1720 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1722 return NT_STATUS_NO_SUCH_FILE;
1725 if (!dir_check_ftype(conn, fattr, dirtype)) {
1727 return NT_STATUS_FILE_IS_A_DIRECTORY;
1729 return NT_STATUS_NO_SUCH_FILE;
1732 if (dirtype_orig & 0x8000) {
1733 /* These will never be set for POSIX. */
1734 return NT_STATUS_NO_SUCH_FILE;
1738 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1739 return NT_STATUS_FILE_IS_A_DIRECTORY;
1742 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1743 return NT_STATUS_NO_SUCH_FILE;
1746 if (dirtype & 0xFF00) {
1747 /* These will never be set for POSIX. */
1748 return NT_STATUS_NO_SUCH_FILE;
1753 return NT_STATUS_NO_SUCH_FILE;
1756 /* Can't delete a directory. */
1758 return NT_STATUS_FILE_IS_A_DIRECTORY;
1763 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1764 return NT_STATUS_OBJECT_NAME_INVALID;
1765 #endif /* JRATEST */
1767 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1769 On a Windows share, a file with read-only dosmode can be opened with
1770 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1771 fails with NT_STATUS_CANNOT_DELETE error.
1773 This semantic causes a problem that a user can not
1774 rename a file with read-only dosmode on a Samba share
1775 from a Windows command prompt (i.e. cmd.exe, but can rename
1776 from Windows Explorer).
1779 if (!lp_delete_readonly(SNUM(conn))) {
1780 if (fattr & aRONLY) {
1781 return NT_STATUS_CANNOT_DELETE;
1785 /* On open checks the open itself will check the share mode, so
1786 don't do it here as we'll get it wrong. */
1788 status = open_file_ntcreate(conn, fname, &sbuf,
1793 FILE_ATTRIBUTE_NORMAL,
1794 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1797 if (NT_STATUS_IS_OK(status)) {
1798 close_file(fsp,NORMAL_CLOSE);
1803 /****************************************************************************
1804 The guts of the unlink command, split out so it may be called by the NT SMB
1806 ****************************************************************************/
1808 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1809 char *name, BOOL has_wild, BOOL can_defer)
1815 NTSTATUS status = NT_STATUS_OK;
1816 SMB_STRUCT_STAT sbuf;
1818 *directory = *mask = 0;
1820 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1821 if (!NT_STATUS_IS_OK(status)) {
1825 p = strrchr_m(name,'/');
1827 pstrcpy(directory,".");
1831 pstrcpy(directory,name);
1836 * We should only check the mangled cache
1837 * here if unix_convert failed. This means
1838 * that the path in 'mask' doesn't exist
1839 * on the file system and so we need to look
1840 * for a possible mangle. This patch from
1841 * Tine Smukavec <valentin.smukavec@hermes.si>.
1844 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1845 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1848 pstrcat(directory,"/");
1849 pstrcat(directory,mask);
1851 dirtype = FILE_ATTRIBUTE_NORMAL;
1853 status = can_delete(conn,directory,dirtype,can_defer);
1854 if (!NT_STATUS_IS_OK(status)) {
1858 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1860 notify_fname(conn, directory, -1,
1861 NOTIFY_ACTION_REMOVED);
1864 struct smb_Dir *dir_hnd = NULL;
1868 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
1869 return NT_STATUS_OBJECT_NAME_INVALID;
1872 if (strequal(mask,"????????.???")) {
1876 status = check_name(conn, directory);
1877 if (!NT_STATUS_IS_OK(status)) {
1881 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1882 if (dir_hnd == NULL) {
1883 return map_nt_error_from_unix(errno);
1886 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1887 the pattern matches against the long name, otherwise the short name
1888 We don't implement this yet XXXX
1891 status = NT_STATUS_NO_SUCH_FILE;
1893 while ((dname = ReadDirName(dir_hnd, &offset))) {
1896 pstrcpy(fname,dname);
1898 if (!is_visible_file(conn, directory, dname, &st, True)) {
1902 /* Quick check for "." and ".." */
1903 if (fname[0] == '.') {
1904 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1909 if(!mask_match(fname, mask, conn->case_sensitive)) {
1913 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1914 status = can_delete(conn, fname, dirtype, can_defer);
1915 if (!NT_STATUS_IS_OK(status)) {
1918 if (SMB_VFS_UNLINK(conn,fname) == 0) {
1920 DEBUG(3,("unlink_internals: succesful unlink "
1922 notify_action(conn, directory, dname,
1923 -1, NOTIFY_ACTION_REMOVED);
1930 if (count == 0 && NT_STATUS_IS_OK(status)) {
1931 status = map_nt_error_from_unix(errno);
1937 /****************************************************************************
1939 ****************************************************************************/
1941 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1948 BOOL path_contains_wcard = False;
1950 START_PROFILE(SMBunlink);
1952 dirtype = SVAL(inbuf,smb_vwv0);
1954 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
1955 if (!NT_STATUS_IS_OK(status)) {
1956 END_PROFILE(SMBunlink);
1957 return ERROR_NT(status);
1960 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1962 DEBUG(3,("reply_unlink : %s\n",name));
1964 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
1966 if (!NT_STATUS_IS_OK(status)) {
1967 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1968 /* We have re-scheduled this call. */
1971 return ERROR_NT(status);
1975 * Win2k needs a changenotify request response before it will
1976 * update after a rename..
1978 process_pending_change_notify_queue((time_t)0);
1980 outsize = set_message(outbuf,0,0,False);
1982 END_PROFILE(SMBunlink);
1986 /****************************************************************************
1988 ****************************************************************************/
1990 static void fail_readraw(void)
1993 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1995 exit_server_cleanly(errstr);
1998 #if defined(WITH_SENDFILE)
1999 /****************************************************************************
2000 Fake (read/write) sendfile. Returns -1 on read or write fail.
2001 ****************************************************************************/
2003 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2007 /* Paranioa check... */
2008 if (nread > bufsize) {
2013 ret = read_file(fsp,buf,startpos,nread);
2019 /* If we had a short read, fill with zeros. */
2021 memset(buf, '\0', nread - ret);
2024 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2028 return (ssize_t)nread;
2032 /****************************************************************************
2033 Use sendfile in readbraw.
2034 ****************************************************************************/
2036 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2037 ssize_t mincount, char *outbuf, int out_buffsize)
2041 #if defined(WITH_SENDFILE)
2043 * We can only use sendfile on a non-chained packet
2044 * but we can use on a non-oplocked file. tridge proved this
2045 * on a train in Germany :-). JRA.
2046 * reply_readbraw has already checked the length.
2049 if ( (chain_size == 0) && (nread > 0) &&
2050 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2053 _smb_setlen(outbuf,nread);
2054 header.data = (uint8 *)outbuf;
2058 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2059 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2060 if (errno == ENOSYS) {
2061 goto normal_readbraw;
2065 * Special hack for broken Linux with no working sendfile. If we
2066 * return EINTR we sent the header but not the rest of the data.
2067 * Fake this up by doing read/write calls.
2069 if (errno == EINTR) {
2070 /* Ensure we don't do this again. */
2071 set_use_sendfile(SNUM(conn), False);
2072 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2074 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2075 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2076 fsp->fsp_name, strerror(errno) ));
2077 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2082 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2083 fsp->fsp_name, strerror(errno) ));
2084 exit_server_cleanly("send_file_readbraw sendfile failed");
2094 ret = read_file(fsp,outbuf+4,startpos,nread);
2095 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2104 _smb_setlen(outbuf,ret);
2105 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2109 /****************************************************************************
2110 Reply to a readbraw (core+ protocol).
2111 ****************************************************************************/
2113 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2115 ssize_t maxcount,mincount;
2118 char *header = outbuf;
2120 START_PROFILE(SMBreadbraw);
2122 if (srv_is_signing_active()) {
2123 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2127 * Special check if an oplock break has been issued
2128 * and the readraw request croses on the wire, we must
2129 * return a zero length response here.
2132 fsp = file_fsp(inbuf,smb_vwv0);
2134 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2136 * fsp could be NULL here so use the value from the packet. JRA.
2138 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2139 _smb_setlen(header,0);
2140 if (write_data(smbd_server_fd(),header,4) != 4)
2142 END_PROFILE(SMBreadbraw);
2146 CHECK_FSP(fsp,conn);
2148 flush_write_cache(fsp, READRAW_FLUSH);
2150 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2151 if(CVAL(inbuf,smb_wct) == 10) {
2153 * This is a large offset (64 bit) read.
2155 #ifdef LARGE_SMB_OFF_T
2157 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2159 #else /* !LARGE_SMB_OFF_T */
2162 * Ensure we haven't been sent a >32 bit offset.
2165 if(IVAL(inbuf,smb_vwv8) != 0) {
2166 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2167 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2168 _smb_setlen(header,0);
2169 if (write_data(smbd_server_fd(),header,4) != 4)
2171 END_PROFILE(SMBreadbraw);
2175 #endif /* LARGE_SMB_OFF_T */
2178 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2179 _smb_setlen(header,0);
2180 if (write_data(smbd_server_fd(),header,4) != 4)
2182 END_PROFILE(SMBreadbraw);
2186 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2187 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2189 /* ensure we don't overrun the packet size */
2190 maxcount = MIN(65535,maxcount);
2192 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2196 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2200 if (startpos >= size) {
2203 nread = MIN(maxcount,(size - startpos));
2207 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2208 if (nread < mincount)
2212 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2213 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2215 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2217 DEBUG(5,("readbraw finished\n"));
2218 END_PROFILE(SMBreadbraw);
2223 #define DBGC_CLASS DBGC_LOCKING
2225 /****************************************************************************
2226 Reply to a lockread (core+ protocol).
2227 ****************************************************************************/
2229 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2237 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2238 struct byte_range_lock *br_lck = NULL;
2239 START_PROFILE(SMBlockread);
2241 CHECK_FSP(fsp,conn);
2242 if (!CHECK_READ(fsp,inbuf)) {
2243 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2246 release_level_2_oplocks_on_change(fsp);
2248 numtoread = SVAL(inbuf,smb_vwv1);
2249 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2251 outsize = set_message(outbuf,5,3,True);
2252 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2253 data = smb_buf(outbuf) + 3;
2256 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2257 * protocol request that predates the read/write lock concept.
2258 * Thus instead of asking for a read lock here we need to ask
2259 * for a write lock. JRA.
2260 * Note that the requested lock size is unaffected by max_recv.
2263 br_lck = do_lock(fsp,
2264 (uint32)SVAL(inbuf,smb_pid),
2265 (SMB_BIG_UINT)numtoread,
2266 (SMB_BIG_UINT)startpos,
2269 False, /* Non-blocking lock. */
2271 TALLOC_FREE(br_lck);
2273 if (NT_STATUS_V(status)) {
2274 END_PROFILE(SMBlockread);
2275 return ERROR_NT(status);
2279 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2282 if (numtoread > max_recv) {
2283 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2284 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2285 (unsigned int)numtoread, (unsigned int)max_recv ));
2286 numtoread = MIN(numtoread,max_recv);
2288 nread = read_file(fsp,data,startpos,numtoread);
2291 END_PROFILE(SMBlockread);
2292 return(UNIXERROR(ERRDOS,ERRnoaccess));
2296 SSVAL(outbuf,smb_vwv0,nread);
2297 SSVAL(outbuf,smb_vwv5,nread+3);
2298 SSVAL(smb_buf(outbuf),1,nread);
2300 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2301 fsp->fnum, (int)numtoread, (int)nread));
2303 END_PROFILE(SMBlockread);
2308 #define DBGC_CLASS DBGC_ALL
2310 /****************************************************************************
2312 ****************************************************************************/
2314 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2321 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2322 START_PROFILE(SMBread);
2324 CHECK_FSP(fsp,conn);
2325 if (!CHECK_READ(fsp,inbuf)) {
2326 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2329 numtoread = SVAL(inbuf,smb_vwv1);
2330 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2332 outsize = set_message(outbuf,5,3,True);
2333 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2335 * The requested read size cannot be greater than max_recv. JRA.
2337 if (numtoread > max_recv) {
2338 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2339 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2340 (unsigned int)numtoread, (unsigned int)max_recv ));
2341 numtoread = MIN(numtoread,max_recv);
2344 data = smb_buf(outbuf) + 3;
2346 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2347 END_PROFILE(SMBread);
2348 return ERROR_DOS(ERRDOS,ERRlock);
2352 nread = read_file(fsp,data,startpos,numtoread);
2355 END_PROFILE(SMBread);
2356 return(UNIXERROR(ERRDOS,ERRnoaccess));
2360 SSVAL(outbuf,smb_vwv0,nread);
2361 SSVAL(outbuf,smb_vwv5,nread+3);
2362 SCVAL(smb_buf(outbuf),0,1);
2363 SSVAL(smb_buf(outbuf),1,nread);
2365 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2366 fsp->fnum, (int)numtoread, (int)nread ) );
2368 END_PROFILE(SMBread);
2372 /****************************************************************************
2373 Reply to a read and X - possibly using sendfile.
2374 ****************************************************************************/
2376 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2377 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2381 char *data = smb_buf(outbuf);
2383 #if defined(WITH_SENDFILE)
2385 * We can only use sendfile on a non-chained packet
2386 * but we can use on a non-oplocked file. tridge proved this
2387 * on a train in Germany :-). JRA.
2390 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2391 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2392 SMB_STRUCT_STAT sbuf;
2395 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2396 return(UNIXERROR(ERRDOS,ERRnoaccess));
2398 if (startpos > sbuf.st_size)
2401 if (smb_maxcnt > (sbuf.st_size - startpos))
2402 smb_maxcnt = (sbuf.st_size - startpos);
2404 if (smb_maxcnt == 0)
2408 * Set up the packet header before send. We
2409 * assume here the sendfile will work (get the
2410 * correct amount of data).
2413 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2414 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2415 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2416 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2417 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2418 SCVAL(outbuf,smb_vwv0,0xFF);
2419 set_message(outbuf,12,smb_maxcnt,False);
2420 header.data = (uint8 *)outbuf;
2421 header.length = data - outbuf;
2424 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2425 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2426 if (errno == ENOSYS) {
2431 * Special hack for broken Linux with no working sendfile. If we
2432 * return EINTR we sent the header but not the rest of the data.
2433 * Fake this up by doing read/write calls.
2436 if (errno == EINTR) {
2437 /* Ensure we don't do this again. */
2438 set_use_sendfile(SNUM(conn), False);
2439 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2441 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2442 len_outbuf - (data-outbuf))) == -1) {
2443 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2444 fsp->fsp_name, strerror(errno) ));
2445 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2447 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2448 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2449 /* Returning -1 here means successful sendfile. */
2453 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2454 fsp->fsp_name, strerror(errno) ));
2455 exit_server_cleanly("send_file_readX sendfile failed");
2458 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2459 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2460 /* Returning -1 here means successful sendfile. */
2468 nread = read_file(fsp,data,startpos,smb_maxcnt);
2471 return(UNIXERROR(ERRDOS,ERRnoaccess));
2474 outsize = set_message(outbuf,12,nread,False);
2475 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2476 SSVAL(outbuf,smb_vwv5,nread);
2477 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2478 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2479 SSVAL(smb_buf(outbuf),-2,nread);
2481 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2482 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2484 /* Returning the number of bytes we want to send back - including header. */
2488 /****************************************************************************
2489 Reply to a read and X.
2490 ****************************************************************************/
2492 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2494 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2495 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2497 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2499 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2502 START_PROFILE(SMBreadX);
2504 /* If it's an IPC, pass off the pipe handler. */
2506 END_PROFILE(SMBreadX);
2507 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2510 CHECK_FSP(fsp,conn);
2511 if (!CHECK_READ(fsp,inbuf)) {
2512 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2515 set_message(outbuf,12,0,True);
2517 if (global_client_caps & CAP_LARGE_READX) {
2518 if (SVAL(inbuf,smb_vwv7) == 1) {
2519 smb_maxcnt |= (1<<16);
2521 if (smb_maxcnt > BUFFER_SIZE) {
2522 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2523 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2524 END_PROFILE(SMBreadX);
2525 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2529 if(CVAL(inbuf,smb_wct) == 12) {
2530 #ifdef LARGE_SMB_OFF_T
2532 * This is a large offset (64 bit) read.
2534 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2536 #else /* !LARGE_SMB_OFF_T */
2539 * Ensure we haven't been sent a >32 bit offset.
2542 if(IVAL(inbuf,smb_vwv10) != 0) {
2543 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2544 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2545 END_PROFILE(SMBreadX);
2546 return ERROR_DOS(ERRDOS,ERRbadaccess);
2549 #endif /* LARGE_SMB_OFF_T */
2553 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2554 END_PROFILE(SMBreadX);
2555 return ERROR_DOS(ERRDOS,ERRlock);
2558 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2559 END_PROFILE(SMBreadX);
2563 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2565 nread = chain_reply(inbuf,outbuf,length,bufsize);
2567 END_PROFILE(SMBreadX);
2571 /****************************************************************************
2572 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2573 ****************************************************************************/
2575 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2578 ssize_t total_written=0;
2579 size_t numtowrite=0;
2584 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2586 START_PROFILE(SMBwritebraw);
2588 if (srv_is_signing_active()) {
2589 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2592 CHECK_FSP(fsp,conn);
2593 if (!CHECK_WRITE(fsp)) {
2594 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2597 tcount = IVAL(inbuf,smb_vwv1);
2598 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2599 write_through = BITSETW(inbuf+smb_vwv7,0);
2601 /* We have to deal with slightly different formats depending
2602 on whether we are using the core+ or lanman1.0 protocol */
2604 if(Protocol <= PROTOCOL_COREPLUS) {
2605 numtowrite = SVAL(smb_buf(inbuf),-2);
2606 data = smb_buf(inbuf);
2608 numtowrite = SVAL(inbuf,smb_vwv10);
2609 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2612 /* force the error type */
2613 SCVAL(inbuf,smb_com,SMBwritec);
2614 SCVAL(outbuf,smb_com,SMBwritec);
2616 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2617 END_PROFILE(SMBwritebraw);
2618 return(ERROR_DOS(ERRDOS,ERRlock));
2622 nwritten = write_file(fsp,data,startpos,numtowrite);
2624 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2625 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2627 if (nwritten < (ssize_t)numtowrite) {
2628 END_PROFILE(SMBwritebraw);
2629 return(UNIXERROR(ERRHRD,ERRdiskfull));
2632 total_written = nwritten;
2634 /* Return a message to the redirector to tell it to send more bytes */
2635 SCVAL(outbuf,smb_com,SMBwritebraw);
2636 SSVALS(outbuf,smb_vwv0,-1);
2637 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2639 if (!send_smb(smbd_server_fd(),outbuf))
2640 exit_server_cleanly("reply_writebraw: send_smb failed.");
2642 /* Now read the raw data into the buffer and write it */
2643 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2644 exit_server_cleanly("secondary writebraw failed");
2647 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2648 numtowrite = smb_len(inbuf);
2650 /* Set up outbuf to return the correct return */
2651 outsize = set_message(outbuf,1,0,True);
2652 SCVAL(outbuf,smb_com,SMBwritec);
2654 if (numtowrite != 0) {
2656 if (numtowrite > BUFFER_SIZE) {
2657 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2658 (unsigned int)numtowrite ));
2659 exit_server_cleanly("secondary writebraw failed");
2662 if (tcount > nwritten+numtowrite) {
2663 DEBUG(3,("Client overestimated the write %d %d %d\n",
2664 (int)tcount,(int)nwritten,(int)numtowrite));
2667 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2668 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2670 exit_server_cleanly("secondary writebraw failed");
2673 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2674 if (nwritten == -1) {
2675 END_PROFILE(SMBwritebraw);
2676 return(UNIXERROR(ERRHRD,ERRdiskfull));
2679 if (nwritten < (ssize_t)numtowrite) {
2680 SCVAL(outbuf,smb_rcls,ERRHRD);
2681 SSVAL(outbuf,smb_err,ERRdiskfull);
2685 total_written += nwritten;
2688 SSVAL(outbuf,smb_vwv0,total_written);
2690 sync_file(conn, fsp, write_through);
2692 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2693 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2695 /* we won't return a status if write through is not selected - this follows what WfWg does */
2696 END_PROFILE(SMBwritebraw);
2697 if (!write_through && total_written==tcount) {
2699 #if RABBIT_PELLET_FIX
2701 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2702 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2704 if (!send_keepalive(smbd_server_fd()))
2705 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2714 #define DBGC_CLASS DBGC_LOCKING
2716 /****************************************************************************
2717 Reply to a writeunlock (core+).
2718 ****************************************************************************/
2720 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2721 int size, int dum_buffsize)
2723 ssize_t nwritten = -1;
2727 NTSTATUS status = NT_STATUS_OK;
2728 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2730 START_PROFILE(SMBwriteunlock);
2732 CHECK_FSP(fsp,conn);
2733 if (!CHECK_WRITE(fsp)) {
2734 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2737 numtowrite = SVAL(inbuf,smb_vwv1);
2738 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2739 data = smb_buf(inbuf) + 3;
2741 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2742 END_PROFILE(SMBwriteunlock);
2743 return ERROR_DOS(ERRDOS,ERRlock);
2746 /* The special X/Open SMB protocol handling of
2747 zero length writes is *NOT* done for
2749 if(numtowrite == 0) {
2752 nwritten = write_file(fsp,data,startpos,numtowrite);
2755 sync_file(conn, fsp, False /* write through */);
2757 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2758 END_PROFILE(SMBwriteunlock);
2759 return(UNIXERROR(ERRHRD,ERRdiskfull));
2763 status = do_unlock(fsp,
2764 (uint32)SVAL(inbuf,smb_pid),
2765 (SMB_BIG_UINT)numtowrite,
2766 (SMB_BIG_UINT)startpos,
2769 if (NT_STATUS_V(status)) {
2770 END_PROFILE(SMBwriteunlock);
2771 return ERROR_NT(status);
2775 outsize = set_message(outbuf,1,0,True);
2777 SSVAL(outbuf,smb_vwv0,nwritten);
2779 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2780 fsp->fnum, (int)numtowrite, (int)nwritten));
2782 END_PROFILE(SMBwriteunlock);
2787 #define DBGC_CLASS DBGC_ALL
2789 /****************************************************************************
2791 ****************************************************************************/
2793 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2796 ssize_t nwritten = -1;
2799 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2801 START_PROFILE(SMBwrite);
2803 /* If it's an IPC, pass off the pipe handler. */
2805 END_PROFILE(SMBwrite);
2806 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2809 CHECK_FSP(fsp,conn);
2810 if (!CHECK_WRITE(fsp)) {
2811 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2814 numtowrite = SVAL(inbuf,smb_vwv1);
2815 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2816 data = smb_buf(inbuf) + 3;
2818 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2819 END_PROFILE(SMBwrite);
2820 return ERROR_DOS(ERRDOS,ERRlock);
2824 * X/Open SMB protocol says that if smb_vwv1 is
2825 * zero then the file size should be extended or
2826 * truncated to the size given in smb_vwv[2-3].
2829 if(numtowrite == 0) {
2831 * This is actually an allocate call, and set EOF. JRA.
2833 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2835 END_PROFILE(SMBwrite);
2836 return ERROR_NT(NT_STATUS_DISK_FULL);
2838 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2840 END_PROFILE(SMBwrite);
2841 return ERROR_NT(NT_STATUS_DISK_FULL);
2844 nwritten = write_file(fsp,data,startpos,numtowrite);
2846 sync_file(conn, fsp, False);
2848 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2849 END_PROFILE(SMBwrite);
2850 return(UNIXERROR(ERRHRD,ERRdiskfull));
2853 outsize = set_message(outbuf,1,0,True);
2855 SSVAL(outbuf,smb_vwv0,nwritten);
2857 if (nwritten < (ssize_t)numtowrite) {
2858 SCVAL(outbuf,smb_rcls,ERRHRD);
2859 SSVAL(outbuf,smb_err,ERRdiskfull);
2862 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2864 END_PROFILE(SMBwrite);
2868 /****************************************************************************
2869 Reply to a write and X.
2870 ****************************************************************************/
2872 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2874 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2875 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2876 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2877 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2878 ssize_t nwritten = -1;
2879 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2880 unsigned int smblen = smb_len(inbuf);
2882 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2883 START_PROFILE(SMBwriteX);
2885 /* If it's an IPC, pass off the pipe handler. */
2887 END_PROFILE(SMBwriteX);
2888 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2891 CHECK_FSP(fsp,conn);
2892 if (!CHECK_WRITE(fsp)) {
2893 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2896 set_message(outbuf,6,0,True);
2898 /* Deal with possible LARGE_WRITEX */
2900 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2903 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2904 END_PROFILE(SMBwriteX);
2905 return ERROR_DOS(ERRDOS,ERRbadmem);
2908 data = smb_base(inbuf) + smb_doff;
2910 if(CVAL(inbuf,smb_wct) == 14) {
2911 #ifdef LARGE_SMB_OFF_T
2913 * This is a large offset (64 bit) write.
2915 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2917 #else /* !LARGE_SMB_OFF_T */
2920 * Ensure we haven't been sent a >32 bit offset.
2923 if(IVAL(inbuf,smb_vwv12) != 0) {
2924 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2925 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2926 END_PROFILE(SMBwriteX);
2927 return ERROR_DOS(ERRDOS,ERRbadaccess);
2930 #endif /* LARGE_SMB_OFF_T */
2933 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2934 END_PROFILE(SMBwriteX);
2935 return ERROR_DOS(ERRDOS,ERRlock);
2938 /* X/Open SMB protocol says that, unlike SMBwrite
2939 if the length is zero then NO truncation is
2940 done, just a write of zero. To truncate a file,
2943 if(numtowrite == 0) {
2947 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2948 fsp,data,startpos,numtowrite)) {
2949 END_PROFILE(SMBwriteX);
2953 nwritten = write_file(fsp,data,startpos,numtowrite);
2956 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2957 END_PROFILE(SMBwriteX);
2958 return(UNIXERROR(ERRHRD,ERRdiskfull));
2961 SSVAL(outbuf,smb_vwv2,nwritten);
2963 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2965 if (nwritten < (ssize_t)numtowrite) {
2966 SCVAL(outbuf,smb_rcls,ERRHRD);
2967 SSVAL(outbuf,smb_err,ERRdiskfull);
2970 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2971 fsp->fnum, (int)numtowrite, (int)nwritten));
2973 sync_file(conn, fsp, write_through);
2975 END_PROFILE(SMBwriteX);
2976 return chain_reply(inbuf,outbuf,length,bufsize);
2979 /****************************************************************************
2981 ****************************************************************************/
2983 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2989 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2990 START_PROFILE(SMBlseek);
2992 CHECK_FSP(fsp,conn);
2994 flush_write_cache(fsp, SEEK_FLUSH);
2996 mode = SVAL(inbuf,smb_vwv1) & 3;
2997 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2998 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3007 res = fsp->fh->pos + startpos;
3018 if (umode == SEEK_END) {
3019 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3020 if(errno == EINVAL) {
3021 SMB_OFF_T current_pos = startpos;
3022 SMB_STRUCT_STAT sbuf;
3024 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3025 END_PROFILE(SMBlseek);
3026 return(UNIXERROR(ERRDOS,ERRnoaccess));
3029 current_pos += sbuf.st_size;
3031 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3036 END_PROFILE(SMBlseek);
3037 return(UNIXERROR(ERRDOS,ERRnoaccess));
3043 outsize = set_message(outbuf,2,0,True);
3044 SIVAL(outbuf,smb_vwv0,res);
3046 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3047 fsp->fnum, (double)startpos, (double)res, mode));
3049 END_PROFILE(SMBlseek);
3053 /****************************************************************************
3055 ****************************************************************************/
3057 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3059 int outsize = set_message(outbuf,0,0,False);
3060 uint16 fnum = SVAL(inbuf,smb_vwv0);
3061 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3062 START_PROFILE(SMBflush);
3065 CHECK_FSP(fsp,conn);
3068 file_sync_all(conn);
3070 sync_file(conn,fsp, True);
3073 DEBUG(3,("flush\n"));
3074 END_PROFILE(SMBflush);
3078 /****************************************************************************
3080 conn POINTER CAN BE NULL HERE !
3081 ****************************************************************************/
3083 int reply_exit(connection_struct *conn,
3084 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3087 START_PROFILE(SMBexit);
3089 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3091 outsize = set_message(outbuf,0,0,False);
3093 DEBUG(3,("exit\n"));
3095 END_PROFILE(SMBexit);
3099 /****************************************************************************
3100 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3101 ****************************************************************************/
3103 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3108 int32 eclass = 0, err = 0;
3109 files_struct *fsp = NULL;
3110 START_PROFILE(SMBclose);
3112 outsize = set_message(outbuf,0,0,False);
3114 /* If it's an IPC, pass off to the pipe handler. */
3116 END_PROFILE(SMBclose);
3117 return reply_pipe_close(conn, inbuf,outbuf);
3120 fsp = file_fsp(inbuf,smb_vwv0);
3123 * We can only use CHECK_FSP if we know it's not a directory.
3126 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3127 END_PROFILE(SMBclose);
3128 return ERROR_DOS(ERRDOS,ERRbadfid);
3131 if(fsp->is_directory) {
3133 * Special case - close NT SMB directory handle.
3135 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3136 close_file(fsp,NORMAL_CLOSE);
3139 * Close ordinary file.
3143 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3144 fsp->fh->fd, fsp->fnum,
3145 conn->num_files_open));
3148 * Take care of any time sent in the close.
3151 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3152 fsp_set_pending_modtime(fsp, mtime);
3155 * close_file() returns the unix errno if an error
3156 * was detected on close - normally this is due to
3157 * a disk full error. If not then it was probably an I/O error.
3160 if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
3162 END_PROFILE(SMBclose);
3163 return (UNIXERROR(ERRHRD,ERRgeneral));
3167 /* We have a cached error */
3169 END_PROFILE(SMBclose);
3170 return ERROR_DOS(eclass,err);
3173 END_PROFILE(SMBclose);
3177 /****************************************************************************
3178 Reply to a writeclose (Core+ protocol).
3179 ****************************************************************************/
3181 int reply_writeclose(connection_struct *conn,
3182 char *inbuf,char *outbuf, int size, int dum_buffsize)
3185 ssize_t nwritten = -1;
3191 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3192 START_PROFILE(SMBwriteclose);
3194 CHECK_FSP(fsp,conn);
3195 if (!CHECK_WRITE(fsp)) {
3196 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3199 numtowrite = SVAL(inbuf,smb_vwv1);
3200 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3201 mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3202 data = smb_buf(inbuf) + 1;
3204 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3205 END_PROFILE(SMBwriteclose);
3206 return ERROR_DOS(ERRDOS,ERRlock);
3209 nwritten = write_file(fsp,data,startpos,numtowrite);
3211 set_filetime(conn, fsp->fsp_name,mtime);
3214 * More insanity. W2K only closes the file if writelen > 0.
3219 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3221 close_err = close_file(fsp,NORMAL_CLOSE);
3224 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3225 fsp->fnum, (int)numtowrite, (int)nwritten,
3226 conn->num_files_open));
3228 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3229 END_PROFILE(SMBwriteclose);
3230 return(UNIXERROR(ERRHRD,ERRdiskfull));
3233 if(close_err != 0) {
3235 END_PROFILE(SMBwriteclose);
3236 return(UNIXERROR(ERRHRD,ERRgeneral));
3239 outsize = set_message(outbuf,1,0,True);
3241 SSVAL(outbuf,smb_vwv0,nwritten);
3242 END_PROFILE(SMBwriteclose);
3247 #define DBGC_CLASS DBGC_LOCKING
3249 /****************************************************************************
3251 ****************************************************************************/
3253 int reply_lock(connection_struct *conn,
3254 char *inbuf,char *outbuf, int length, int dum_buffsize)
3256 int outsize = set_message(outbuf,0,0,False);
3257 SMB_BIG_UINT count,offset;
3259 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3260 struct byte_range_lock *br_lck = NULL;
3262 START_PROFILE(SMBlock);
3264 CHECK_FSP(fsp,conn);
3266 release_level_2_oplocks_on_change(fsp);
3268 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3269 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3271 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3272 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3274 br_lck = do_lock(fsp,
3275 (uint32)SVAL(inbuf,smb_pid),
3280 False, /* Non-blocking lock. */
3283 TALLOC_FREE(br_lck);
3285 if (NT_STATUS_V(status)) {
3286 END_PROFILE(SMBlock);
3287 return ERROR_NT(status);
3290 END_PROFILE(SMBlock);
3294 /****************************************************************************
3296 ****************************************************************************/
3298 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3301 int outsize = set_message(outbuf,0,0,False);
3302 SMB_BIG_UINT count,offset;
3304 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3305 START_PROFILE(SMBunlock);
3307 CHECK_FSP(fsp,conn);
3309 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3310 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3312 status = do_unlock(fsp,
3313 (uint32)SVAL(inbuf,smb_pid),
3318 if (NT_STATUS_V(status)) {
3319 END_PROFILE(SMBunlock);
3320 return ERROR_NT(status);
3323 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3324 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3326 END_PROFILE(SMBunlock);
3331 #define DBGC_CLASS DBGC_ALL
3333 /****************************************************************************
3335 conn POINTER CAN BE NULL HERE !
3336 ****************************************************************************/
3338 int reply_tdis(connection_struct *conn,
3339 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3341 int outsize = set_message(outbuf,0,0,False);
3343 START_PROFILE(SMBtdis);
3345 vuid = SVAL(inbuf,smb_uid);
3348 DEBUG(4,("Invalid connection in tdis\n"));
3349 END_PROFILE(SMBtdis);
3350 return ERROR_DOS(ERRSRV,ERRinvnid);
3355 close_cnum(conn,vuid);
3357 END_PROFILE(SMBtdis);
3361 /****************************************************************************
3363 conn POINTER CAN BE NULL HERE !
3364 ****************************************************************************/
3366 int reply_echo(connection_struct *conn,
3367 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3369 int smb_reverb = SVAL(inbuf,smb_vwv0);
3371 unsigned int data_len = smb_buflen(inbuf);
3372 int outsize = set_message(outbuf,1,data_len,True);
3373 START_PROFILE(SMBecho);
3375 if (data_len > BUFFER_SIZE) {
3376 DEBUG(0,("reply_echo: data_len too large.\n"));
3377 END_PROFILE(SMBecho);
3381 /* copy any incoming data back out */
3383 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3385 if (smb_reverb > 100) {
3386 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3390 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3391 SSVAL(outbuf,smb_vwv0,seq_num);
3393 smb_setlen(outbuf,outsize - 4);
3396 if (!send_smb(smbd_server_fd(),outbuf))
3397 exit_server_cleanly("reply_echo: send_smb failed.");
3400 DEBUG(3,("echo %d times\n", smb_reverb));
3404 END_PROFILE(SMBecho);
3408 /****************************************************************************
3409 Reply to a printopen.
3410 ****************************************************************************/
3412 int reply_printopen(connection_struct *conn,
3413 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3419 START_PROFILE(SMBsplopen);
3421 if (!CAN_PRINT(conn)) {
3422 END_PROFILE(SMBsplopen);
3423 return ERROR_DOS(ERRDOS,ERRnoaccess);
3426 /* Open for exclusive use, write only. */
3427 status = print_fsp_open(conn, NULL, &fsp);
3429 if (!NT_STATUS_IS_OK(status)) {
3430 END_PROFILE(SMBsplopen);
3431 return(ERROR_NT(status));
3434 outsize = set_message(outbuf,1,0,True);
3435 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3437 DEBUG(3,("openprint fd=%d fnum=%d\n",
3438 fsp->fh->fd, fsp->fnum));
3440 END_PROFILE(SMBsplopen);
3444 /****************************************************************************
3445 Reply to a printclose.
3446 ****************************************************************************/
3448 int reply_printclose(connection_struct *conn,
3449 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3451 int outsize = set_message(outbuf,0,0,False);
3452 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3454 START_PROFILE(SMBsplclose);
3456 CHECK_FSP(fsp,conn);
3458 if (!CAN_PRINT(conn)) {
3459 END_PROFILE(SMBsplclose);
3460 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3463 DEBUG(3,("printclose fd=%d fnum=%d\n",
3464 fsp->fh->fd,fsp->fnum));
3466 close_err = close_file(fsp,NORMAL_CLOSE);
3468 if(close_err != 0) {
3470 END_PROFILE(SMBsplclose);
3471 return(UNIXERROR(ERRHRD,ERRgeneral));
3474 END_PROFILE(SMBsplclose);
3478 /****************************************************************************
3479 Reply to a printqueue.
3480 ****************************************************************************/
3482 int reply_printqueue(connection_struct *conn,
3483 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3485 int outsize = set_message(outbuf,2,3,True);
3486 int max_count = SVAL(inbuf,smb_vwv0);
3487 int start_index = SVAL(inbuf,smb_vwv1);
3488 START_PROFILE(SMBsplretq);
3490 /* we used to allow the client to get the cnum wrong, but that
3491 is really quite gross and only worked when there was only
3492 one printer - I think we should now only accept it if they
3493 get it right (tridge) */
3494 if (!CAN_PRINT(conn)) {
3495 END_PROFILE(SMBsplretq);
3496 return ERROR_DOS(ERRDOS,ERRnoaccess);
3499 SSVAL(outbuf,smb_vwv0,0);
3500 SSVAL(outbuf,smb_vwv1,0);
3501 SCVAL(smb_buf(outbuf),0,1);
3502 SSVAL(smb_buf(outbuf),1,0);
3504 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3505 start_index, max_count));
3508 print_queue_struct *queue = NULL;
3509 print_status_struct status;
3510 char *p = smb_buf(outbuf) + 3;
3511 int count = print_queue_status(SNUM(conn), &queue, &status);
3512 int num_to_get = ABS(max_count);
3513 int first = (max_count>0?start_index:start_index+max_count+1);
3519 num_to_get = MIN(num_to_get,count-first);
3522 for (i=first;i<first+num_to_get;i++) {
3523 srv_put_dos_date2(p,0,queue[i].time);
3524 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3525 SSVAL(p,5, queue[i].job);
3526 SIVAL(p,7,queue[i].size);
3528 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3533 outsize = set_message(outbuf,2,28*count+3,False);
3534 SSVAL(outbuf,smb_vwv0,count);
3535 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3536 SCVAL(smb_buf(outbuf),0,1);
3537 SSVAL(smb_buf(outbuf),1,28*count);
3542 DEBUG(3,("%d entries returned in queue\n",count));
3545 END_PROFILE(SMBsplretq);
3549 /****************************************************************************
3550 Reply to a printwrite.
3551 ****************************************************************************/
3553 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3556 int outsize = set_message(outbuf,0,0,False);
3558 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3560 START_PROFILE(SMBsplwr);
3562 if (!CAN_PRINT(conn)) {
3563 END_PROFILE(SMBsplwr);
3564 return ERROR_DOS(ERRDOS,ERRnoaccess);
3567 CHECK_FSP(fsp,conn);
3568 if (!CHECK_WRITE(fsp)) {
3569 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3572 numtowrite = SVAL(smb_buf(inbuf),1);
3573 data = smb_buf(inbuf) + 3;
3575 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3576 END_PROFILE(SMBsplwr);
3577 return(UNIXERROR(ERRHRD,ERRdiskfull));
3580 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3582 END_PROFILE(SMBsplwr);
3586 /****************************************************************************
3588 ****************************************************************************/
3590 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3595 SMB_STRUCT_STAT sbuf;
3597 START_PROFILE(SMBmkdir);
3599 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3600 if (!NT_STATUS_IS_OK(status)) {
3601 END_PROFILE(SMBmkdir);
3602 return ERROR_NT(status);
3605 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3607 status = unix_convert(conn, directory, False, NULL, &sbuf);
3608 if (!NT_STATUS_IS_OK(status)) {
3609 END_PROFILE(SMBmkdir);
3610 return ERROR_NT(status);
3613 status = create_directory(conn, directory);
3615 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3617 if (!NT_STATUS_IS_OK(status)) {
3619 if (!use_nt_status()
3620 && NT_STATUS_EQUAL(status,
3621 NT_STATUS_OBJECT_NAME_COLLISION)) {
3623 * Yes, in the DOS error code case we get a
3624 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3625 * samba4 torture test.
3627 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3630 END_PROFILE(SMBmkdir);
3631 return ERROR_NT(status);
3634 outsize = set_message(outbuf,0,0,False);
3636 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3638 END_PROFILE(SMBmkdir);
3642 /****************************************************************************
3643 Static function used by reply_rmdir to delete an entire directory
3644 tree recursively. Return True on ok, False on fail.
3645 ****************************************************************************/
3647 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3649 const char *dname = NULL;
3652 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3657 while((dname = ReadDirName(dir_hnd, &offset))) {
3661 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3664 if (!is_visible_file(conn, directory, dname, &st, False))
3667 /* Construct the full name. */
3668 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3674 pstrcpy(fullname, directory);
3675 pstrcat(fullname, "/");
3676 pstrcat(fullname, dname);
3678 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3683 if(st.st_mode & S_IFDIR) {
3684 if(!recursive_rmdir(conn, fullname)) {
3688 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3692 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3701 /****************************************************************************
3702 The internals of the rmdir code - called elsewhere.
3703 ****************************************************************************/
3705 BOOL rmdir_internals(connection_struct *conn, const char *directory)
3710 ret = SMB_VFS_RMDIR(conn,directory);
3715 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3717 * Check to see if the only thing in this directory are
3718 * vetoed files/directories. If so then delete them and
3719 * retry. If we fail to delete any of them (and we *don't*
3720 * do a recursive delete) then fail the rmdir.
3724 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3726 if(dir_hnd == NULL) {
3731 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3732 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3734 if (!is_visible_file(conn, directory, dname, &st, False))
3736 if(!IS_VETO_PATH(conn, dname)) {
3743 /* We only have veto files/directories. Recursive delete. */
3745 RewindDir(dir_hnd,&dirpos);
3746 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3749 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3751 if (!is_visible_file(conn, directory, dname, &st, False))
3754 /* Construct the full name. */
3755 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3760 pstrcpy(fullname, directory);
3761 pstrcat(fullname, "/");
3762 pstrcat(fullname, dname);
3764 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3766 if(st.st_mode & S_IFDIR) {
3767 if(lp_recursive_veto_delete(SNUM(conn))) {
3768 if(!recursive_rmdir(conn, fullname))
3771 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3773 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3777 /* Retry the rmdir */
3778 ret = SMB_VFS_RMDIR(conn,directory);
3784 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3785 "%s\n", directory,strerror(errno)));
3791 const char *dirname;
3793 if (parent_dirname_talloc(tmp_talloc_ctx(), directory,
3794 &parent_dir, &dirname)) {
3795 notify_action(conn, parent_dir, dirname, -1,
3796 NOTIFY_ACTION_REMOVED);
3797 TALLOC_FREE(parent_dir); /* Not strictly necessary */
3804 /****************************************************************************
3806 ****************************************************************************/
3808 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3812 SMB_STRUCT_STAT sbuf;
3814 START_PROFILE(SMBrmdir);
3816 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3817 if (!NT_STATUS_IS_OK(status)) {
3818 END_PROFILE(SMBrmdir);
3819 return ERROR_NT(status);
3822 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3824 status = unix_convert(conn, directory, False, NULL, &sbuf);
3825 if (!NT_STATUS_IS_OK(status)) {
3826 END_PROFILE(SMBrmdir);
3827 return ERROR_NT(status);
3830 status = check_name(conn, directory);
3831 if (!NT_STATUS_IS_OK(status)) {
3832 END_PROFILE(SMBrmdir);
3833 return ERROR_NT(status);
3836 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3837 if (!rmdir_internals(conn, directory)) {
3838 END_PROFILE(SMBrmdir);
3839 return UNIXERROR(ERRDOS, ERRbadpath);
3842 outsize = set_message(outbuf,0,0,False);
3844 DEBUG( 3, ( "rmdir %s\n", directory ) );
3846 END_PROFILE(SMBrmdir);
3850 /*******************************************************************
3851 Resolve wildcards in a filename rename.
3852 Note that name is in UNIX charset and thus potentially can be more
3853 than fstring buffer (255 bytes) especially in default UTF-8 case.
3854 Therefore, we use pstring inside and all calls should ensure that
3855 name2 is at least pstring-long (they do already)
3856 ********************************************************************/
3858 static BOOL resolve_wildcards(const char *name1, char *name2)
3860 pstring root1,root2;
3862 char *p,*p2, *pname1, *pname2;
3863 int available_space, actual_space;
3866 pname1 = strrchr_m(name1,'/');
3867 pname2 = strrchr_m(name2,'/');
3869 if (!pname1 || !pname2)
3872 pstrcpy(root1,pname1);
3873 pstrcpy(root2,pname2);
3874 p = strrchr_m(root1,'.');
3881 p = strrchr_m(root2,'.');
3895 } else if (*p2 == '*') {
3911 } else if (*p2 == '*') {
3921 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3924 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3925 if (actual_space >= available_space - 1) {
3926 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3927 actual_space - available_space));
3930 pstrcpy_base(pname2, root2, name2);
3936 /****************************************************************************
3937 Ensure open files have their names updated. Updated to notify other smbd's
3939 ****************************************************************************/
3941 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
3942 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
3945 BOOL did_rename = False;
3947 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3948 /* fsp_name is a relative path under the fsp. To change this for other
3949 sharepaths we need to manipulate relative paths. */
3950 /* TODO - create the absolute path and manipulate the newname
3951 relative to the sharepath. */
3952 if (fsp->conn != conn) {
3955 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3956 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3957 fsp->fsp_name, newname ));
3958 string_set(&fsp->fsp_name, newname);
3963 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3964 (unsigned int)dev, (double)inode, newname ));
3967 /* Send messages to all smbd's (not ourself) that the name has changed. */
3968 rename_share_filename(lck, conn->connectpath, newname);
3971 /****************************************************************************
3972 We need to check if the source path is a parent directory of the destination
3973 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
3974 refuse the rename with a sharing violation. Under UNIX the above call can
3975 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
3976 probably need to check that the client is a Windows one before disallowing
3977 this as a UNIX client (one with UNIX extensions) can know the source is a
3978 symlink and make this decision intelligently. Found by an excellent bug
3979 report from <AndyLiebman@aol.com>.
3980 ****************************************************************************/
3982 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
3984 const char *psrc = src;
3985 const char *pdst = dest;
3988 if (psrc[0] == '.' && psrc[1] == '/') {
3991 if (pdst[0] == '.' && pdst[1] == '/') {
3994 if ((slen = strlen(psrc)) > strlen(pdst)) {
3997 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4000 /****************************************************************************
4001 Rename an open file - given an fsp.
4002 ****************************************************************************/
4004 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
4006 SMB_STRUCT_STAT sbuf;
4007 pstring newname_last_component;
4008 NTSTATUS status = NT_STATUS_OK;
4010 struct share_mode_lock *lck = NULL;
4014 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4015 if (!NT_STATUS_IS_OK(status)) {
4019 /* Ensure newname contains a '/' */
4020 if(strrchr_m(newname,'/') == 0) {
4023 pstrcpy(tmpstr, "./");
4024 pstrcat(tmpstr, newname);
4025 pstrcpy(newname, tmpstr);
4029 * Check for special case with case preserving and not
4030 * case sensitive. If the old last component differs from the original
4031 * last component only by case, then we should allow
4032 * the rename (user is trying to change the case of the
4036 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4037 strequal(newname, fsp->fsp_name)) {
4039 pstring newname_modified_last_component;
4042 * Get the last component of the modified name.
4043 * Note that we guarantee that newname contains a '/'
4046 p = strrchr_m(newname,'/');
4047 pstrcpy(newname_modified_last_component,p+1);
4049 if(strcsequal(newname_modified_last_component,
4050 newname_last_component) == False) {
4052 * Replace the modified last component with
4055 pstrcpy(p+1, newname_last_component);
4060 * If the src and dest names are identical - including case,
4061 * don't do the rename, just return success.
4064 if (strcsequal(fsp->fsp_name, newname)) {
4065 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4067 return NT_STATUS_OK;
4070 dest_exists = vfs_object_exist(conn,newname,NULL);
4072 if(!replace_if_exists && dest_exists) {
4073 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4074 fsp->fsp_name,newname));
4075 return NT_STATUS_OBJECT_NAME_COLLISION;
4078 status = can_rename(conn,newname,attrs,&sbuf);
4080 if (dest_exists && !NT_STATUS_IS_OK(status)) {
4081 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4082 nt_errstr(status), fsp->fsp_name,newname));
4083 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4084 status = NT_STATUS_ACCESS_DENIED;
4088 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4089 return NT_STATUS_ACCESS_DENIED;
4092 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4094 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4095 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4096 fsp->fsp_name,newname));
4097 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4099 return NT_STATUS_OK;
4104 if (errno == ENOTDIR || errno == EISDIR) {
4105 status = NT_STATUS_OBJECT_NAME_COLLISION;
4107 status = map_nt_error_from_unix(errno);
4110 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4111 nt_errstr(status), fsp->fsp_name,newname));
4116 /****************************************************************************
4117 The guts of the rename command, split out so it may be called by the NT SMB
4119 ****************************************************************************/
4121 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
4125 pstring last_component_src;
4126 pstring last_component_dest;
4129 NTSTATUS status = NT_STATUS_OK;
4130 SMB_STRUCT_STAT sbuf1, sbuf2;
4131 struct share_mode_lock *lck = NULL;
4133 *directory = *mask = 0;
4138 status = unix_convert(conn, name, has_wild, last_component_src, &sbuf1);
4139 if (!NT_STATUS_IS_OK(status)) {
4143 status = unix_convert(conn, newname, True, last_component_dest, &sbuf2);
4144 if (!NT_STATUS_IS_OK(status)) {
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 (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4178 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4182 * No wildcards - just process the one file.
4184 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4186 /* Add a terminating '/' to the directory name. */
4187 pstrcat(directory,"/");
4188 pstrcat(directory,mask);
4190 /* Ensure newname contains a '/' also */
4191 if(strrchr_m(newname,'/') == 0) {
4194 pstrcpy(tmpstr, "./");
4195 pstrcat(tmpstr, newname);
4196 pstrcpy(newname, tmpstr);
4199 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4200 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4201 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4202 newname, last_component_dest, is_short_name));
4205 * Check for special case with case preserving and not
4206 * case sensitive, if directory and newname are identical,
4207 * and the old last component differs from the original
4208 * last component only by case, then we should allow
4209 * the rename (user is trying to change the case of the
4212 if((conn->case_sensitive == False) &&
4213 (((conn->case_preserve == True) &&
4214 (is_short_name == False)) ||
4215 ((conn->short_case_preserve == True) &&
4216 (is_short_name == True))) &&
4217 strcsequal(directory, newname)) {
4218 pstring modified_last_component;
4221 * Get the last component of the modified name.
4222 * Note that we guarantee that newname contains a '/'
4225 p = strrchr_m(newname,'/');
4226 pstrcpy(modified_last_component,p+1);
4228 if(strcsequal(modified_last_component,
4229 last_component_dest) == False) {
4231 * Replace the modified last component with
4234 pstrcpy(p+1, last_component_dest);
4238 resolve_wildcards(directory,newname);
4241 * The source object must exist.
4244 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4245 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4246 directory,newname));
4248 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4250 * Must return different errors depending on whether the parent
4251 * directory existed or not.
4254 p = strrchr_m(directory, '/');
4256 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4258 if (vfs_object_exist(conn, directory, NULL))
4259 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4260 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4262 status = map_nt_error_from_unix(errno);
4263 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4264 nt_errstr(status), directory,newname));
4269 status = can_rename(conn,directory,attrs,&sbuf1);
4271 if (!NT_STATUS_IS_OK(status)) {
4272 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4273 nt_errstr(status), directory,newname));
4278 * If the src and dest names are identical - including case,
4279 * don't do the rename, just return success.
4282 if (strcsequal(directory, newname)) {
4283 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4284 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4285 return NT_STATUS_OK;
4288 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4289 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4290 directory,newname));
4291 return NT_STATUS_OBJECT_NAME_COLLISION;
4294 if (rename_path_prefix_equal(directory, newname)) {
4295 return NT_STATUS_SHARING_VIOLATION;
4298 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4300 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4301 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4302 directory,newname));
4303 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4305 return NT_STATUS_OK;
4309 if (errno == ENOTDIR || errno == EISDIR) {
4310 status = NT_STATUS_OBJECT_NAME_COLLISION;
4312 status = map_nt_error_from_unix(errno);
4315 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4316 nt_errstr(status), directory,newname));
4321 * Wildcards - process each file that matches.
4323 struct smb_Dir *dir_hnd = NULL;
4328 if (strequal(mask,"????????.???"))
4331 status = check_name(conn, directory);
4332 if (!NT_STATUS_IS_OK(status)) {
4336 dir_hnd = OpenDir(conn, directory, mask, attrs);
4337 if (dir_hnd == NULL) {
4338 return map_nt_error_from_unix(errno);
4341 status = NT_STATUS_NO_SUCH_FILE;
4342 /* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4344 while ((dname = ReadDirName(dir_hnd, &offset))) {
4346 BOOL sysdir_entry = False;
4348 pstrcpy(fname,dname);
4350 /* Quick check for "." and ".." */
4351 if (fname[0] == '.') {
4352 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4354 sysdir_entry = True;
4361 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4365 if(!mask_match(fname, mask, conn->case_sensitive)) {
4370 status = NT_STATUS_OBJECT_NAME_INVALID;
4374 status = NT_STATUS_ACCESS_DENIED;
4375 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4376 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4377 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4378 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status)));
4381 status = can_rename(conn,fname,attrs,&sbuf1);
4382 if (!NT_STATUS_IS_OK(status)) {
4383 DEBUG(6,("rename %s refused\n", fname));
4386 pstrcpy(destname,newname);
4388 if (!resolve_wildcards(fname,destname)) {
4389 DEBUG(6,("resolve_wildcards %s %s failed\n",
4394 if (strcsequal(fname,destname)) {
4395 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4396 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4398 status = NT_STATUS_OK;
4402 if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
4403 DEBUG(6,("file_exist %s\n", destname));
4404 status = NT_STATUS_OBJECT_NAME_COLLISION;
4408 if (rename_path_prefix_equal(fname, destname)) {
4409 return NT_STATUS_SHARING_VIOLATION;
4412 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4414 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4415 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4417 status = NT_STATUS_OK;
4420 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4426 /* Don't think needed any more - JRA. */
4427 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4428 if (!rcdest && bad_path_dest) {
4429 if (ms_has_wild(last_component_dest))
4430 return NT_STATUS_OBJECT_NAME_INVALID;
4431 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4436 if (count == 0 && NT_STATUS_IS_OK(status)) {
4437 status = map_nt_error_from_unix(errno);
4443 /****************************************************************************
4445 ****************************************************************************/
4447 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4454 uint32 attrs = SVAL(inbuf,smb_vwv0);
4456 BOOL path1_contains_wcard = False;
4457 BOOL path2_contains_wcard = False;
4459 START_PROFILE(SMBmv);
4461 p = smb_buf(inbuf) + 1;
4462 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
4463 if (!NT_STATUS_IS_OK(status)) {
4465 return ERROR_NT(status);
4468 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
4469 if (!NT_STATUS_IS_OK(status)) {
4471 return ERROR_NT(status);
4474 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4475 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4477 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4479 status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
4480 if (!NT_STATUS_IS_OK(status)) {
4482 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4483 /* We have re-scheduled this call. */
4486 return ERROR_NT(status);
4490 * Win2k needs a changenotify request response before it will
4491 * update after a rename..
4493 process_pending_change_notify_queue((time_t)0);
4494 outsize = set_message(outbuf,0,0,False);
4500 /*******************************************************************
4501 Copy a file as part of a reply_copy.
4502 ******************************************************************/
4505 * TODO: check error codes on all callers
4508 NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
4509 int count, BOOL target_is_directory)
4511 SMB_STRUCT_STAT src_sbuf, sbuf2;
4513 files_struct *fsp1,*fsp2;
4516 uint32 new_create_disposition;
4520 pstrcpy(dest,dest1);
4521 if (target_is_directory) {
4522 char *p = strrchr_m(src,'/');
4532 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4533 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4536 if (!target_is_directory && count) {
4537 new_create_disposition = FILE_OPEN;
4539 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4540 NULL, NULL, &new_create_disposition, NULL)) {
4541 return NT_STATUS_INVALID_PARAMETER;
4545 status = open_file_ntcreate(conn,src,&src_sbuf,
4547 FILE_SHARE_READ|FILE_SHARE_WRITE,
4550 FILE_ATTRIBUTE_NORMAL,
4554 if (!NT_STATUS_IS_OK(status)) {
4558 dosattrs = dos_mode(conn, src, &src_sbuf);
4559 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4560 ZERO_STRUCTP(&sbuf2);
4563 status = open_file_ntcreate(conn,dest,&sbuf2,
4565 FILE_SHARE_READ|FILE_SHARE_WRITE,
4566 new_create_disposition,
4572 if (!NT_STATUS_IS_OK(status)) {
4573 close_file(fsp1,ERROR_CLOSE);
4577 if ((ofun&3) == 1) {
4578 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4579 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4581 * Stop the copy from occurring.
4584 src_sbuf.st_size = 0;
4588 if (src_sbuf.st_size) {
4589 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4592 close_file(fsp1,NORMAL_CLOSE);
4594 /* Ensure the modtime is set correctly on the destination file. */
4595 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4598 * As we are opening fsp1 read-only we only expect
4599 * an error on close on fsp2 if we are out of space.
4600 * Thus we don't look at the error return from the
4603 close_err = close_file(fsp2,NORMAL_CLOSE);
4605 if (close_err != 0) {
4606 return map_nt_error_from_unix(close_err);
4609 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4610 return NT_STATUS_DISK_FULL;
4613 return NT_STATUS_OK;
4616 /****************************************************************************
4617 Reply to a file copy.
4618 ****************************************************************************/
4620 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4625 pstring mask,newname;
4628 int error = ERRnoaccess;
4632 int tid2 = SVAL(inbuf,smb_vwv0);
4633 int ofun = SVAL(inbuf,smb_vwv1);
4634 int flags = SVAL(inbuf,smb_vwv2);
4635 BOOL target_is_directory=False;
4636 BOOL path_contains_wcard1 = False;
4637 BOOL path_contains_wcard2 = False;
4638 SMB_STRUCT_STAT sbuf1, sbuf2;
4640 START_PROFILE(SMBcopy);
4642 *directory = *mask = 0;
4645 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
4646 if (!NT_STATUS_IS_OK(status)) {
4647 END_PROFILE(SMBcopy);
4648 return ERROR_NT(status);
4650 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
4651 if (!NT_STATUS_IS_OK(status)) {
4652 END_PROFILE(SMBcopy);
4653 return ERROR_NT(status);
4656 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4658 if (tid2 != conn->cnum) {
4659 /* can't currently handle inter share copies XXXX */
4660 DEBUG(3,("Rejecting inter-share copy\n"));
4661 END_PROFILE(SMBcopy);
4662 return ERROR_DOS(ERRSRV,ERRinvdevice);
4665 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4666 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4668 status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
4669 if (!NT_STATUS_IS_OK(status)) {
4670 END_PROFILE(SMBcopy);
4671 return ERROR_NT(status);
4674 status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
4675 if (!NT_STATUS_IS_OK(status)) {
4676 END_PROFILE(SMBcopy);
4677 return ERROR_NT(status);
4680 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4682 if ((flags&1) && target_is_directory) {
4683 END_PROFILE(SMBcopy);
4684 return ERROR_DOS(ERRDOS,ERRbadfile);
4687 if ((flags&2) && !target_is_directory) {
4688 END_PROFILE(SMBcopy);
4689 return ERROR_DOS(ERRDOS,ERRbadpath);
4692 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4693 /* wants a tree copy! XXXX */
4694 DEBUG(3,("Rejecting tree copy\n"));
4695 END_PROFILE(SMBcopy);
4696 return ERROR_DOS(ERRSRV,ERRerror);
4699 p = strrchr_m(name,'/');
4701 pstrcpy(directory,"./");
4705 pstrcpy(directory,name);
4710 * We should only check the mangled cache
4711 * here if unix_convert failed. This means
4712 * that the path in 'mask' doesn't exist
4713 * on the file system and so we need to look
4714 * for a possible mangle. This patch from
4715 * Tine Smukavec <valentin.smukavec@hermes.si>.
4718 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4719 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4721 has_wild = path_contains_wcard1;
4724 pstrcat(directory,"/");
4725 pstrcat(directory,mask);
4726 if (resolve_wildcards(directory,newname)
4727 && NT_STATUS_IS_OK(status = copy_file(
4728 directory,newname,conn,ofun,
4729 count,target_is_directory)))
4731 if(!count && !NT_STATUS_IS_OK(status)) {
4732 END_PROFILE(SMBcopy);
4733 return ERROR_NT(status);
4736 exists = vfs_file_exist(conn,directory,NULL);
4739 struct smb_Dir *dir_hnd = NULL;
4744 if (strequal(mask,"????????.???"))
4747 status = check_name(conn, directory);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 return ERROR_NT(status);
4752 dir_hnd = OpenDir(conn, directory, mask, 0);
4753 if (dir_hnd == NULL) {
4754 status = map_nt_error_from_unix(errno);
4755 return ERROR_NT(status);
4760 while ((dname = ReadDirName(dir_hnd, &offset))) {
4762 pstrcpy(fname,dname);
4764 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4768 if(!mask_match(fname, mask, conn->case_sensitive)) {
4772 error = ERRnoaccess;
4773 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4774 pstrcpy(destname,newname);
4775 if (resolve_wildcards(fname,destname) &&
4776 NT_STATUS_IS_OK(status = copy_file(
4777 fname,destname,conn,ofun,
4778 count,target_is_directory))) {
4781 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4788 /* Error on close... */
4790 END_PROFILE(SMBcopy);
4791 return(UNIXERROR(ERRHRD,ERRgeneral));
4794 END_PROFILE(SMBcopy);
4795 return ERROR_DOS(ERRDOS,error);
4798 outsize = set_message(outbuf,1,0,True);
4799 SSVAL(outbuf,smb_vwv0,count);
4801 END_PROFILE(SMBcopy);
4805 /****************************************************************************
4807 ****************************************************************************/
4809 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4816 START_PROFILE(pathworks_setdir);
4819 if (!CAN_SETDIR(snum)) {
4820 END_PROFILE(pathworks_setdir);
4821 return ERROR_DOS(ERRDOS,ERRnoaccess);
4824 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4825 if (!NT_STATUS_IS_OK(status)) {
4826 END_PROFILE(pathworks_setdir);
4827 return ERROR_NT(status);
4830 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4832 if (strlen(newdir) != 0) {
4833 if (!vfs_directory_exist(conn,newdir,NULL)) {
4834 END_PROFILE(pathworks_setdir);
4835 return ERROR_DOS(ERRDOS,ERRbadpath);
4837 set_conn_connectpath(conn,newdir);
4840 outsize = set_message(outbuf,0,0,False);
4841 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4843 DEBUG(3,("setdir %s\n", newdir));
4845 END_PROFILE(pathworks_setdir);
4850 #define DBGC_CLASS DBGC_LOCKING
4852 /****************************************************************************
4853 Get a lock pid, dealing with large count requests.
4854 ****************************************************************************/
4856 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4858 if(!large_file_format)
4859 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
4861 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4864 /****************************************************************************
4865 Get a lock count, dealing with large count requests.
4866 ****************************************************************************/
4868 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4870 SMB_BIG_UINT count = 0;
4872 if(!large_file_format) {
4873 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4876 #if defined(HAVE_LONGLONG)
4877 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4878 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4879 #else /* HAVE_LONGLONG */
4882 * NT4.x seems to be broken in that it sends large file (64 bit)
4883 * lockingX calls even if the CAP_LARGE_FILES was *not*
4884 * negotiated. For boxes without large unsigned ints truncate the
4885 * lock count by dropping the top 32 bits.
4888 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4889 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4890 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4891 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4892 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4895 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4896 #endif /* HAVE_LONGLONG */
4902 #if !defined(HAVE_LONGLONG)
4903 /****************************************************************************
4904 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4905 ****************************************************************************/
4907 static uint32 map_lock_offset(uint32 high, uint32 low)
4911 uint32 highcopy = high;
4914 * Try and find out how many significant bits there are in high.
4917 for(i = 0; highcopy; i++)
4921 * We use 31 bits not 32 here as POSIX
4922 * lock offsets may not be negative.
4925 mask = (~0) << (31 - i);
4928 return 0; /* Fail. */
4934 #endif /* !defined(HAVE_LONGLONG) */
4936 /****************************************************************************
4937 Get a lock offset, dealing with large offset requests.
4938 ****************************************************************************/
4940 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4942 SMB_BIG_UINT offset = 0;
4946 if(!large_file_format) {
4947 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4950 #if defined(HAVE_LONGLONG)
4951 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4952 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4953 #else /* HAVE_LONGLONG */
4956 * NT4.x seems to be broken in that it sends large file (64 bit)
4957 * lockingX calls even if the CAP_LARGE_FILES was *not*
4958 * negotiated. For boxes without large unsigned ints mangle the
4959 * lock offset by mapping the top 32 bits onto the lower 32.
4962 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4963 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4964 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4967 if((new_low = map_lock_offset(high, low)) == 0) {
4969 return (SMB_BIG_UINT)-1;
4972 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4973 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4974 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4975 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4978 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4979 #endif /* HAVE_LONGLONG */
4985 /****************************************************************************
4986 Reply to a lockingX request.
4987 ****************************************************************************/
4989 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
4990 int length, int bufsize)
4992 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4993 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4994 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4995 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4996 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4997 SMB_BIG_UINT count = 0, offset = 0;
4999 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5002 BOOL large_file_format =
5003 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5005 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5007 START_PROFILE(SMBlockingX);
5009 CHECK_FSP(fsp,conn);
5011 data = smb_buf(inbuf);
5013 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5014 /* we don't support these - and CANCEL_LOCK makes w2k
5015 and XP reboot so I don't really want to be
5016 compatible! (tridge) */
5017 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5020 /* Check if this is an oplock break on a file
5021 we have granted an oplock on.
5023 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5024 /* Client can insist on breaking to none. */
5025 BOOL break_to_none = (oplocklevel == 0);
5028 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5029 "for fnum = %d\n", (unsigned int)oplocklevel,
5033 * Make sure we have granted an exclusive or batch oplock on
5037 if (fsp->oplock_type == 0) {
5039 /* The Samba4 nbench simulator doesn't understand
5040 the difference between break to level2 and break
5041 to none from level2 - it sends oplock break
5042 replies in both cases. Don't keep logging an error
5043 message here - just ignore it. JRA. */
5045 DEBUG(5,("reply_lockingX: Error : oplock break from "
5046 "client for fnum = %d (oplock=%d) and no "
5047 "oplock granted on this file (%s).\n",
5048 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5050 /* if this is a pure oplock break request then don't
5052 if (num_locks == 0 && num_ulocks == 0) {
5053 END_PROFILE(SMBlockingX);
5056 END_PROFILE(SMBlockingX);
5057 return ERROR_DOS(ERRDOS,ERRlock);
5061 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5063 result = remove_oplock(fsp);
5065 result = downgrade_oplock(fsp);
5069 DEBUG(0, ("reply_lockingX: error in removing "
5070 "oplock on file %s\n", fsp->fsp_name));
5071 /* Hmmm. Is this panic justified? */
5072 smb_panic("internal tdb error");
5075 reply_to_oplock_break_requests(fsp);
5077 /* if this is a pure oplock break request then don't send a
5079 if (num_locks == 0 && num_ulocks == 0) {
5080 /* Sanity check - ensure a pure oplock break is not a
5082 if(CVAL(inbuf,smb_vwv0) != 0xff)
5083 DEBUG(0,("reply_lockingX: Error : pure oplock "
5084 "break is a chained %d request !\n",
5085 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5086 END_PROFILE(SMBlockingX);
5092 * We do this check *after* we have checked this is not a oplock break
5093 * response message. JRA.
5096 release_level_2_oplocks_on_change(fsp);
5098 /* Data now points at the beginning of the list
5099 of smb_unlkrng structs */
5100 for(i = 0; i < (int)num_ulocks; i++) {
5101 lock_pid = get_lock_pid( data, i, large_file_format);
5102 count = get_lock_count( data, i, large_file_format);
5103 offset = get_lock_offset( data, i, large_file_format, &err);
5106 * There is no error code marked "stupid client bug".... :-).
5109 END_PROFILE(SMBlockingX);
5110 return ERROR_DOS(ERRDOS,ERRnoaccess);
5113 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5114 "pid %u, file %s\n", (double)offset, (double)count,
5115 (unsigned int)lock_pid, fsp->fsp_name ));
5117 status = do_unlock(fsp,
5123 if (NT_STATUS_V(status)) {
5124 END_PROFILE(SMBlockingX);
5125 return ERROR_NT(status);
5129 /* Setup the timeout in seconds. */
5131 if (!lp_blocking_locks(SNUM(conn))) {
5135 /* Now do any requested locks */
5136 data += ((large_file_format ? 20 : 10)*num_ulocks);
5138 /* Data now points at the beginning of the list
5139 of smb_lkrng structs */
5141 for(i = 0; i < (int)num_locks; i++) {
5142 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5143 READ_LOCK:WRITE_LOCK);
5144 lock_pid = get_lock_pid( data, i, large_file_format);
5145 count = get_lock_count( data, i, large_file_format);
5146 offset = get_lock_offset( data, i, large_file_format, &err);
5149 * There is no error code marked "stupid client bug".... :-).
5152 END_PROFILE(SMBlockingX);
5153 return ERROR_DOS(ERRDOS,ERRnoaccess);
5156 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5157 "%u, file %s timeout = %d\n", (double)offset,
5158 (double)count, (unsigned int)lock_pid,
5159 fsp->fsp_name, (int)lock_timeout ));
5161 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5162 if (lp_blocking_locks(SNUM(conn))) {
5164 /* Schedule a message to ourselves to
5165 remove the blocking lock record and
5166 return the right error. */
5168 if (!blocking_lock_cancel(fsp,
5174 NT_STATUS_FILE_LOCK_CONFLICT)) {
5175 END_PROFILE(SMBlockingX);
5176 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5179 /* Remove a matching pending lock. */
5180 status = do_lock_cancel(fsp,
5186 BOOL blocking_lock = lock_timeout ? True : False;
5187 BOOL defer_lock = False;
5188 struct byte_range_lock *br_lck;
5190 br_lck = do_lock(fsp,
5199 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5200 /* Windows internal resolution for blocking locks seems
5201 to be about 200ms... Don't wait for less than that. JRA. */
5202 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5203 lock_timeout = lp_lock_spin_time();
5208 /* This heuristic seems to match W2K3 very well. If a
5209 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5210 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5211 far as I can tell. Replacement for do_lock_spin(). JRA. */
5213 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5214 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5216 lock_timeout = lp_lock_spin_time();
5219 if (br_lck && defer_lock) {
5221 * A blocking lock was requested. Package up
5222 * this smb into a queued request and push it
5223 * onto the blocking lock queue.
5225 if(push_blocking_lock_request(br_lck,
5235 TALLOC_FREE(br_lck);
5236 END_PROFILE(SMBlockingX);
5241 TALLOC_FREE(br_lck);
5244 if (NT_STATUS_V(status)) {
5245 END_PROFILE(SMBlockingX);
5246 return ERROR_NT(status);
5250 /* If any of the above locks failed, then we must unlock
5251 all of the previous locks (X/Open spec). */
5253 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5257 * Ensure we don't do a remove on the lock that just failed,
5258 * as under POSIX rules, if we have a lock already there, we
5259 * will delete it (and we shouldn't) .....
5261 for(i--; i >= 0; i--) {
5262 lock_pid = get_lock_pid( data, i, large_file_format);
5263 count = get_lock_count( data, i, large_file_format);
5264 offset = get_lock_offset( data, i, large_file_format,
5268 * There is no error code marked "stupid client
5272 END_PROFILE(SMBlockingX);
5273 return ERROR_DOS(ERRDOS,ERRnoaccess);
5282 END_PROFILE(SMBlockingX);
5283 return ERROR_NT(status);
5286 set_message(outbuf,2,0,True);
5288 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5289 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5291 END_PROFILE(SMBlockingX);
5292 return chain_reply(inbuf,outbuf,length,bufsize);
5296 #define DBGC_CLASS DBGC_ALL
5298 /****************************************************************************
5299 Reply to a SMBreadbmpx (read block multiplex) request.
5300 ****************************************************************************/
5302 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5313 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5314 START_PROFILE(SMBreadBmpx);
5316 /* this function doesn't seem to work - disable by default */
5317 if (!lp_readbmpx()) {
5318 END_PROFILE(SMBreadBmpx);
5319 return ERROR_DOS(ERRSRV,ERRuseSTD);
5322 outsize = set_message(outbuf,8,0,True);
5324 CHECK_FSP(fsp,conn);
5325 if (!CHECK_READ(fsp,inbuf)) {
5326 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5329 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5330 maxcount = SVAL(inbuf,smb_vwv3);
5332 data = smb_buf(outbuf);
5333 pad = ((long)data)%4;
5338 max_per_packet = bufsize-(outsize+pad);
5342 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5343 END_PROFILE(SMBreadBmpx);
5344 return ERROR_DOS(ERRDOS,ERRlock);
5348 size_t N = MIN(max_per_packet,tcount-total_read);
5350 nread = read_file(fsp,data,startpos,N);
5355 if (nread < (ssize_t)N)
5356 tcount = total_read + nread;
5358 set_message(outbuf,8,nread+pad,False);
5359 SIVAL(outbuf,smb_vwv0,startpos);
5360 SSVAL(outbuf,smb_vwv2,tcount);
5361 SSVAL(outbuf,smb_vwv6,nread);
5362 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5365 if (!send_smb(smbd_server_fd(),outbuf))
5366 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5368 total_read += nread;
5370 } while (total_read < (ssize_t)tcount);
5372 END_PROFILE(SMBreadBmpx);
5376 /****************************************************************************
5377 Reply to a SMBsetattrE.
5378 ****************************************************************************/
5380 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5382 struct utimbuf unix_times;
5384 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5385 START_PROFILE(SMBsetattrE);
5387 outsize = set_message(outbuf,0,0,False);
5389 if(!fsp || (fsp->conn != conn)) {
5390 END_PROFILE(SMBsetattrE);
5391 return ERROR_DOS(ERRDOS,ERRbadfid);
5395 * Convert the DOS times into unix times. Ignore create
5396 * time as UNIX can't set this.
5399 unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
5400 unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
5403 * Patch from Ray Frush <frush@engr.colostate.edu>
5404 * Sometimes times are sent as zero - ignore them.
5407 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5408 /* Ignore request */
5409 if( DEBUGLVL( 3 ) ) {
5410 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5411 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5413 END_PROFILE(SMBsetattrE);
5415 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5416 /* set modify time = to access time if modify time was unset */
5417 unix_times.modtime = unix_times.actime;
5420 /* Set the date on this file */
5421 /* Should we set pending modtime here ? JRA */
5422 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5423 END_PROFILE(SMBsetattrE);
5424 return ERROR_DOS(ERRDOS,ERRnoaccess);
5427 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5428 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5430 END_PROFILE(SMBsetattrE);
5435 /* Back from the dead for OS/2..... JRA. */
5437 /****************************************************************************
5438 Reply to a SMBwritebmpx (write block multiplex primary) request.
5439 ****************************************************************************/
5441 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5444 ssize_t nwritten = -1;
5451 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5452 START_PROFILE(SMBwriteBmpx);
5454 CHECK_FSP(fsp,conn);
5455 if (!CHECK_WRITE(fsp)) {
5456 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5458 if (HAS_CACHED_ERROR(fsp)) {
5459 return(CACHED_ERROR(fsp));
5462 tcount = SVAL(inbuf,smb_vwv1);
5463 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5464 write_through = BITSETW(inbuf+smb_vwv7,0);
5465 numtowrite = SVAL(inbuf,smb_vwv10);
5466 smb_doff = SVAL(inbuf,smb_vwv11);
5468 data = smb_base(inbuf) + smb_doff;
5470 /* If this fails we need to send an SMBwriteC response,
5471 not an SMBwritebmpx - set this up now so we don't forget */
5472 SCVAL(outbuf,smb_com,SMBwritec);
5474 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5475 END_PROFILE(SMBwriteBmpx);
5476 return(ERROR_DOS(ERRDOS,ERRlock));
5479 nwritten = write_file(fsp,data,startpos,numtowrite);
5481 sync_file(conn, fsp, write_through);
5483 if(nwritten < (ssize_t)numtowrite) {
5484 END_PROFILE(SMBwriteBmpx);
5485 return(UNIXERROR(ERRHRD,ERRdiskfull));
5488 /* If the maximum to be written to this file
5489 is greater than what we just wrote then set
5490 up a secondary struct to be attached to this
5491 fd, we will use this to cache error messages etc. */
5493 if((ssize_t)tcount > nwritten) {
5494 write_bmpx_struct *wbms;
5495 if(fsp->wbmpx_ptr != NULL)
5496 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5498 wbms = SMB_MALLOC_P(write_bmpx_struct);
5500 DEBUG(0,("Out of memory in reply_readmpx\n"));
5501 END_PROFILE(SMBwriteBmpx);
5502 return(ERROR_DOS(ERRSRV,ERRnoresource));
5504 wbms->wr_mode = write_through;
5505 wbms->wr_discard = False; /* No errors yet */
5506 wbms->wr_total_written = nwritten;
5507 wbms->wr_errclass = 0;
5509 fsp->wbmpx_ptr = wbms;
5512 /* We are returning successfully, set the message type back to
5514 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5516 outsize = set_message(outbuf,1,0,True);
5518 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5520 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5521 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5523 if (write_through && tcount==nwritten) {
5524 /* We need to send both a primary and a secondary response */
5525 smb_setlen(outbuf,outsize - 4);
5527 if (!send_smb(smbd_server_fd(),outbuf))
5528 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5530 /* Now the secondary */
5531 outsize = set_message(outbuf,1,0,True);
5532 SCVAL(outbuf,smb_com,SMBwritec);
5533 SSVAL(outbuf,smb_vwv0,nwritten);
5536 END_PROFILE(SMBwriteBmpx);
5540 /****************************************************************************
5541 Reply to a SMBwritebs (write block multiplex secondary) request.
5542 ****************************************************************************/
5544 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5547 ssize_t nwritten = -1;
5554 write_bmpx_struct *wbms;
5555 BOOL send_response = False;
5556 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5557 START_PROFILE(SMBwriteBs);
5559 CHECK_FSP(fsp,conn);
5560 if (!CHECK_WRITE(fsp)) {
5561 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5564 tcount = SVAL(inbuf,smb_vwv1);
5565 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5566 numtowrite = SVAL(inbuf,smb_vwv6);
5567 smb_doff = SVAL(inbuf,smb_vwv7);
5569 data = smb_base(inbuf) + smb_doff;
5571 /* We need to send an SMBwriteC response, not an SMBwritebs */
5572 SCVAL(outbuf,smb_com,SMBwritec);
5574 /* This fd should have an auxiliary struct attached,
5575 check that it does */
5576 wbms = fsp->wbmpx_ptr;
5578 END_PROFILE(SMBwriteBs);
5582 /* If write through is set we can return errors, else we must cache them */
5583 write_through = wbms->wr_mode;
5585 /* Check for an earlier error */
5586 if(wbms->wr_discard) {
5587 END_PROFILE(SMBwriteBs);
5588 return -1; /* Just discard the packet */
5591 nwritten = write_file(fsp,data,startpos,numtowrite);
5593 sync_file(conn, fsp, write_through);
5595 if (nwritten < (ssize_t)numtowrite) {
5597 /* We are returning an error - we can delete the aux struct */
5600 fsp->wbmpx_ptr = NULL;
5601 END_PROFILE(SMBwriteBs);
5602 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5604 wbms->wr_errclass = ERRHRD;
5605 wbms->wr_error = ERRdiskfull;
5606 wbms->wr_status = NT_STATUS_DISK_FULL;
5607 wbms->wr_discard = True;
5608 END_PROFILE(SMBwriteBs);
5612 /* Increment the total written, if this matches tcount
5613 we can discard the auxiliary struct (hurrah !) and return a writeC */
5614 wbms->wr_total_written += nwritten;
5615 if(wbms->wr_total_written >= tcount) {
5616 if (write_through) {
5617 outsize = set_message(outbuf,1,0,True);
5618 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5619 send_response = True;
5623 fsp->wbmpx_ptr = NULL;
5627 END_PROFILE(SMBwriteBs);
5631 END_PROFILE(SMBwriteBs);
5635 /****************************************************************************
5636 Reply to a SMBgetattrE.
5637 ****************************************************************************/
5639 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5641 SMB_STRUCT_STAT sbuf;
5644 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5645 START_PROFILE(SMBgetattrE);
5647 outsize = set_message(outbuf,11,0,True);
5649 if(!fsp || (fsp->conn != conn)) {
5650 END_PROFILE(SMBgetattrE);
5651 return ERROR_DOS(ERRDOS,ERRbadfid);
5654 /* Do an fstat on this file */
5655 if(fsp_stat(fsp, &sbuf)) {
5656 END_PROFILE(SMBgetattrE);
5657 return(UNIXERROR(ERRDOS,ERRnoaccess));
5660 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5663 * Convert the times into dos times. Set create
5664 * date to be last modify date as UNIX doesn't save
5668 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5669 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5670 /* Should we check pending modtime here ? JRA */
5671 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5674 SIVAL(outbuf,smb_vwv6,0);
5675 SIVAL(outbuf,smb_vwv8,0);
5677 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5678 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5679 SIVAL(outbuf,smb_vwv8,allocation_size);
5681 SSVAL(outbuf,smb_vwv10, mode);
5683 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5685 END_PROFILE(SMBgetattrE);