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 status = check_name(conn, fname);
802 if (!NT_STATUS_IS_OK(status)) {
803 END_PROFILE(SMBsetatr);
804 return ERROR_NT(status);
807 if (fname[0] == '.' && fname[1] == '\0') {
809 * Not sure here is the right place to catch this
810 * condition. Might be moved to somewhere else later -- vl
812 END_PROFILE(SMBsetatr);
813 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
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,convert_time_t_to_timespec(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,
1020 SVAL(inbuf,smb_pid),
1022 mask_contains_wcard,
1025 if (!NT_STATUS_IS_OK(nt_status)) {
1026 return ERROR_NT(nt_status);
1028 dptr_num = dptr_dnum(conn->dirptr);
1030 dirtype = dptr_attr(dptr_num);
1033 DEBUG(4,("dptr_num is %d\n",dptr_num));
1035 if ((dirtype&0x1F) == aVOLID) {
1036 memcpy(p,status,21);
1037 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1038 0,aVOLID,0,!allow_long_path_components);
1039 dptr_fill(p+12,dptr_num);
1040 if (dptr_zero(p+12) && (status_len==0)) {
1045 p += DIR_STRUCT_SIZE;
1048 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1050 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1051 conn->dirpath,lp_dontdescend(SNUM(conn))));
1052 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1053 check_descend = True;
1056 for (i=numentries;(i<maxentries) && !finished;i++) {
1057 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1059 memcpy(p,status,21);
1060 make_dir_struct(p,mask,fname,size, mode,date,
1061 !allow_long_path_components);
1062 if (!dptr_fill(p+12,dptr_num)) {
1066 p += DIR_STRUCT_SIZE;
1073 /* If we were called as SMBffirst with smb_search_id == NULL
1074 and no entries were found then return error and close dirptr
1077 if (numentries == 0) {
1078 dptr_close(&dptr_num);
1079 } else if(expect_close && status_len == 0) {
1080 /* Close the dptr - we know it's gone */
1081 dptr_close(&dptr_num);
1084 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1085 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1086 dptr_close(&dptr_num);
1089 if ((numentries == 0) && !mask_contains_wcard) {
1090 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1093 SSVAL(outbuf,smb_vwv0,numentries);
1094 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1095 SCVAL(smb_buf(outbuf),0,5);
1096 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1098 /* The replies here are never long name. */
1099 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1100 if (!allow_long_path_components) {
1101 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1104 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1105 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1107 outsize += DIR_STRUCT_SIZE*numentries;
1108 smb_setlen(outbuf,outsize - 4);
1110 if ((! *directory) && dptr_path(dptr_num))
1111 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1113 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1114 smb_fn_name(CVAL(inbuf,smb_com)),
1115 mask, directory, dirtype, numentries, maxentries ) );
1117 END_PROFILE(SMBsearch);
1121 /****************************************************************************
1122 Reply to a fclose (stop directory search).
1123 ****************************************************************************/
1125 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1134 BOOL path_contains_wcard = False;
1136 START_PROFILE(SMBfclose);
1138 if (lp_posix_pathnames()) {
1139 END_PROFILE(SMBfclose);
1140 return reply_unknown(inbuf, outbuf);
1143 outsize = set_message(outbuf,1,0,True);
1144 p = smb_buf(inbuf) + 1;
1145 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1146 if (!NT_STATUS_IS_OK(err)) {
1147 END_PROFILE(SMBfclose);
1148 return ERROR_NT(err);
1151 status_len = SVAL(p,0);
1154 if (status_len == 0) {
1155 END_PROFILE(SMBfclose);
1156 return ERROR_DOS(ERRSRV,ERRsrverror);
1159 memcpy(status,p,21);
1161 if(dptr_fetch(status+12,&dptr_num)) {
1162 /* Close the dptr - we know it's gone */
1163 dptr_close(&dptr_num);
1166 SSVAL(outbuf,smb_vwv0,0);
1168 DEBUG(3,("search close\n"));
1170 END_PROFILE(SMBfclose);
1174 /****************************************************************************
1176 ****************************************************************************/
1178 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1186 SMB_STRUCT_STAT sbuf;
1188 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1190 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1193 uint32 create_disposition;
1194 uint32 create_options = 0;
1196 START_PROFILE(SMBopen);
1198 deny_mode = SVAL(inbuf,smb_vwv0);
1200 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 END_PROFILE(SMBopen);
1203 return ERROR_NT(status);
1206 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1208 status = unix_convert(conn, fname, False, NULL, &sbuf);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 END_PROFILE(SMBopen);
1211 return ERROR_NT(status);
1214 status = check_name(conn, fname);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 END_PROFILE(SMBopen);
1217 return ERROR_NT(status);
1220 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1221 &access_mask, &share_mode, &create_disposition, &create_options)) {
1222 END_PROFILE(SMBopen);
1223 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1226 status = open_file_ntcreate(conn,fname,&sbuf,
1235 if (!NT_STATUS_IS_OK(status)) {
1236 END_PROFILE(SMBopen);
1237 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1238 /* We have re-scheduled this call. */
1241 return ERROR_NT(status);
1244 size = sbuf.st_size;
1245 fattr = dos_mode(conn,fname,&sbuf);
1246 mtime = sbuf.st_mtime;
1249 DEBUG(3,("attempt to open a directory %s\n",fname));
1250 close_file(fsp,ERROR_CLOSE);
1251 END_PROFILE(SMBopen);
1252 return ERROR_DOS(ERRDOS,ERRnoaccess);
1255 outsize = set_message(outbuf,7,0,True);
1256 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1257 SSVAL(outbuf,smb_vwv1,fattr);
1258 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1259 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1261 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1263 SIVAL(outbuf,smb_vwv4,(uint32)size);
1264 SSVAL(outbuf,smb_vwv6,deny_mode);
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1267 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1270 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1271 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1273 END_PROFILE(SMBopen);
1277 /****************************************************************************
1278 Reply to an open and X.
1279 ****************************************************************************/
1281 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1284 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1285 int deny_mode = SVAL(inbuf,smb_vwv3);
1286 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1287 /* Breakout the oplock request bits so we can set the
1288 reply bits separately. */
1289 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1290 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1291 int oplock_request = ex_oplock_request | core_oplock_request;
1293 int smb_sattr = SVAL(inbuf,smb_vwv4);
1294 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1296 int smb_ofun = SVAL(inbuf,smb_vwv8);
1299 SMB_STRUCT_STAT sbuf;
1303 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1304 ssize_t retval = -1;
1307 uint32 create_disposition;
1308 uint32 create_options = 0;
1310 START_PROFILE(SMBopenX);
1312 /* If it's an IPC, pass off the pipe handler. */
1314 if (lp_nt_pipe_support()) {
1315 END_PROFILE(SMBopenX);
1316 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1318 END_PROFILE(SMBopenX);
1319 return ERROR_DOS(ERRSRV,ERRaccess);
1323 /* XXXX we need to handle passed times, sattr and flags */
1324 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1325 if (!NT_STATUS_IS_OK(status)) {
1326 END_PROFILE(SMBopenX);
1327 return ERROR_NT(status);
1330 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1332 status = unix_convert(conn, fname, False, NULL, &sbuf);
1333 if (!NT_STATUS_IS_OK(status)) {
1334 END_PROFILE(SMBopenX);
1335 return ERROR_NT(status);
1338 status = check_name(conn, fname);
1339 if (!NT_STATUS_IS_OK(status)) {
1340 END_PROFILE(SMBopenX);
1341 return ERROR_NT(status);
1344 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1347 &create_disposition,
1349 END_PROFILE(SMBopenX);
1350 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1353 status = open_file_ntcreate(conn,fname,&sbuf,
1362 if (!NT_STATUS_IS_OK(status)) {
1363 END_PROFILE(SMBopenX);
1364 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1365 /* We have re-scheduled this call. */
1368 return ERROR_NT(status);
1371 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1372 if the file is truncated or created. */
1373 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1374 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1375 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1376 close_file(fsp,ERROR_CLOSE);
1377 END_PROFILE(SMBopenX);
1378 return ERROR_NT(NT_STATUS_DISK_FULL);
1380 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1382 close_file(fsp,ERROR_CLOSE);
1383 END_PROFILE(SMBopenX);
1384 return ERROR_NT(NT_STATUS_DISK_FULL);
1386 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1389 fattr = dos_mode(conn,fname,&sbuf);
1390 mtime = sbuf.st_mtime;
1392 close_file(fsp,ERROR_CLOSE);
1393 END_PROFILE(SMBopenX);
1394 return ERROR_DOS(ERRDOS,ERRnoaccess);
1397 /* If the caller set the extended oplock request bit
1398 and we granted one (by whatever means) - set the
1399 correct bit for extended oplock reply.
1402 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1403 smb_action |= EXTENDED_OPLOCK_GRANTED;
1406 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1407 smb_action |= EXTENDED_OPLOCK_GRANTED;
1410 /* If the caller set the core oplock request bit
1411 and we granted one (by whatever means) - set the
1412 correct bit for core oplock reply.
1415 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1416 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1419 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1420 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1423 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1424 set_message(outbuf,19,0,True);
1426 set_message(outbuf,15,0,True);
1428 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1429 SSVAL(outbuf,smb_vwv3,fattr);
1430 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1431 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1433 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1435 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1436 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1437 SSVAL(outbuf,smb_vwv11,smb_action);
1439 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1440 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1443 END_PROFILE(SMBopenX);
1444 return chain_reply(inbuf,outbuf,length,bufsize);
1447 /****************************************************************************
1448 Reply to a SMBulogoffX.
1449 conn POINTER CAN BE NULL HERE !
1450 ****************************************************************************/
1452 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1454 uint16 vuid = SVAL(inbuf,smb_uid);
1455 user_struct *vuser = get_valid_user_struct(vuid);
1456 START_PROFILE(SMBulogoffX);
1459 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1461 /* in user level security we are supposed to close any files
1462 open by this user */
1463 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1464 file_close_user(vuid);
1466 invalidate_vuid(vuid);
1468 set_message(outbuf,2,0,True);
1470 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1472 END_PROFILE(SMBulogoffX);
1473 return chain_reply(inbuf,outbuf,length,bufsize);
1476 /****************************************************************************
1477 Reply to a mknew or a create.
1478 ****************************************************************************/
1480 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1485 uint32 fattr = SVAL(inbuf,smb_vwv0);
1486 struct timespec ts[2];
1488 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1489 SMB_STRUCT_STAT sbuf;
1491 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1492 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1493 uint32 create_disposition;
1494 uint32 create_options = 0;
1496 START_PROFILE(SMBcreate);
1498 com = SVAL(inbuf,smb_com);
1500 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1502 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1503 if (!NT_STATUS_IS_OK(status)) {
1504 END_PROFILE(SMBcreate);
1505 return ERROR_NT(status);
1508 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1510 status = unix_convert(conn, fname, False, NULL, &sbuf);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 END_PROFILE(SMBcreate);
1513 return ERROR_NT(status);
1516 status = check_name(conn, fname);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 END_PROFILE(SMBcreate);
1519 return ERROR_NT(status);
1522 if (fattr & aVOLID) {
1523 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1526 if(com == SMBmknew) {
1527 /* We should fail if file exists. */
1528 create_disposition = FILE_CREATE;
1530 /* Create if file doesn't exist, truncate if it does. */
1531 create_disposition = FILE_OVERWRITE_IF;
1534 /* Open file using ntcreate. */
1535 status = open_file_ntcreate(conn,fname,&sbuf,
1544 if (!NT_STATUS_IS_OK(status)) {
1545 END_PROFILE(SMBcreate);
1546 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1547 /* We have re-scheduled this call. */
1550 return ERROR_NT(status);
1553 ts[0] = get_atimespec(&sbuf); /* atime. */
1554 file_ntimes(conn, fname, ts);
1556 outsize = set_message(outbuf,1,0,True);
1557 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1559 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1560 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1563 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1564 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1567 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1568 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1570 END_PROFILE(SMBcreate);
1574 /****************************************************************************
1575 Reply to a create temporary file.
1576 ****************************************************************************/
1578 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1582 uint32 fattr = SVAL(inbuf,smb_vwv0);
1584 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1586 SMB_STRUCT_STAT sbuf;
1589 unsigned int namelen;
1591 START_PROFILE(SMBctemp);
1593 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1594 if (!NT_STATUS_IS_OK(status)) {
1595 END_PROFILE(SMBctemp);
1596 return ERROR_NT(status);
1599 pstrcat(fname,"/TMXXXXXX");
1601 pstrcat(fname,"TMXXXXXX");
1604 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1606 status = unix_convert(conn, fname, False, NULL, &sbuf);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 END_PROFILE(SMBctemp);
1609 return ERROR_NT(status);
1612 status = check_name(conn, fname);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 END_PROFILE(SMBctemp);
1615 return ERROR_NT(status);
1618 tmpfd = smb_mkstemp(fname);
1620 END_PROFILE(SMBctemp);
1621 return(UNIXERROR(ERRDOS,ERRnoaccess));
1624 SMB_VFS_STAT(conn,fname,&sbuf);
1626 /* We should fail if file does not exist. */
1627 status = open_file_ntcreate(conn,fname,&sbuf,
1628 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1629 FILE_SHARE_READ|FILE_SHARE_WRITE,
1636 /* close fd from smb_mkstemp() */
1639 if (!NT_STATUS_IS_OK(status)) {
1640 END_PROFILE(SMBctemp);
1641 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1642 /* We have re-scheduled this call. */
1645 return ERROR_NT(status);
1648 outsize = set_message(outbuf,1,0,True);
1649 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1651 /* the returned filename is relative to the directory */
1652 s = strrchr_m(fname, '/');
1659 p = smb_buf(outbuf);
1661 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1662 thing in the byte section. JRA */
1663 SSVALS(p, 0, -1); /* what is this? not in spec */
1665 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1667 outsize = set_message_end(outbuf, p);
1669 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1670 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1673 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1674 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1677 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1678 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1679 (unsigned int)sbuf.st_mode ) );
1681 END_PROFILE(SMBctemp);
1685 /*******************************************************************
1686 Check if a user is allowed to rename a file.
1687 ********************************************************************/
1689 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1695 if (!CAN_WRITE(conn)) {
1696 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1699 fmode = dos_mode(conn,fname,pst);
1700 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1701 return NT_STATUS_NO_SUCH_FILE;
1704 if (S_ISDIR(pst->st_mode)) {
1705 return NT_STATUS_OK;
1708 status = open_file_ntcreate(conn, fname, pst,
1710 FILE_SHARE_READ|FILE_SHARE_WRITE,
1713 FILE_ATTRIBUTE_NORMAL,
1717 if (!NT_STATUS_IS_OK(status)) {
1720 close_file(fsp,NORMAL_CLOSE);
1721 return NT_STATUS_OK;
1724 /*******************************************************************
1725 Check if a user is allowed to delete a file.
1726 ********************************************************************/
1728 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1729 uint32 dirtype, BOOL can_defer)
1731 SMB_STRUCT_STAT sbuf;
1734 uint32 dirtype_orig = dirtype;
1737 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1739 if (!CAN_WRITE(conn)) {
1740 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1743 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1744 return map_nt_error_from_unix(errno);
1747 fattr = dos_mode(conn,fname,&sbuf);
1749 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1750 dirtype = aDIR|aARCH|aRONLY;
1753 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1755 return NT_STATUS_NO_SUCH_FILE;
1758 if (!dir_check_ftype(conn, fattr, dirtype)) {
1760 return NT_STATUS_FILE_IS_A_DIRECTORY;
1762 return NT_STATUS_NO_SUCH_FILE;
1765 if (dirtype_orig & 0x8000) {
1766 /* These will never be set for POSIX. */
1767 return NT_STATUS_NO_SUCH_FILE;
1771 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1772 return NT_STATUS_FILE_IS_A_DIRECTORY;
1775 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1776 return NT_STATUS_NO_SUCH_FILE;
1779 if (dirtype & 0xFF00) {
1780 /* These will never be set for POSIX. */
1781 return NT_STATUS_NO_SUCH_FILE;
1786 return NT_STATUS_NO_SUCH_FILE;
1789 /* Can't delete a directory. */
1791 return NT_STATUS_FILE_IS_A_DIRECTORY;
1796 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1797 return NT_STATUS_OBJECT_NAME_INVALID;
1798 #endif /* JRATEST */
1800 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1802 On a Windows share, a file with read-only dosmode can be opened with
1803 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1804 fails with NT_STATUS_CANNOT_DELETE error.
1806 This semantic causes a problem that a user can not
1807 rename a file with read-only dosmode on a Samba share
1808 from a Windows command prompt (i.e. cmd.exe, but can rename
1809 from Windows Explorer).
1812 if (!lp_delete_readonly(SNUM(conn))) {
1813 if (fattr & aRONLY) {
1814 return NT_STATUS_CANNOT_DELETE;
1818 /* On open checks the open itself will check the share mode, so
1819 don't do it here as we'll get it wrong. */
1821 status = open_file_ntcreate(conn, fname, &sbuf,
1826 FILE_ATTRIBUTE_NORMAL,
1827 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1830 if (NT_STATUS_IS_OK(status)) {
1831 close_file(fsp,NORMAL_CLOSE);
1836 /****************************************************************************
1837 The guts of the unlink command, split out so it may be called by the NT SMB
1839 ****************************************************************************/
1841 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1842 char *name, BOOL has_wild, BOOL can_defer)
1848 NTSTATUS status = NT_STATUS_OK;
1849 SMB_STRUCT_STAT sbuf;
1851 *directory = *mask = 0;
1853 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1854 if (!NT_STATUS_IS_OK(status)) {
1858 p = strrchr_m(name,'/');
1860 pstrcpy(directory,".");
1864 pstrcpy(directory,name);
1869 * We should only check the mangled cache
1870 * here if unix_convert failed. This means
1871 * that the path in 'mask' doesn't exist
1872 * on the file system and so we need to look
1873 * for a possible mangle. This patch from
1874 * Tine Smukavec <valentin.smukavec@hermes.si>.
1877 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1878 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1881 pstrcat(directory,"/");
1882 pstrcat(directory,mask);
1884 dirtype = FILE_ATTRIBUTE_NORMAL;
1887 status = check_name(conn, directory);
1888 if (!NT_STATUS_IS_OK(status)) {
1892 status = can_delete(conn,directory,dirtype,can_defer);
1893 if (!NT_STATUS_IS_OK(status)) {
1897 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1899 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1900 FILE_NOTIFY_CHANGE_FILE_NAME,
1904 struct smb_Dir *dir_hnd = NULL;
1908 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
1909 return NT_STATUS_OBJECT_NAME_INVALID;
1912 if (strequal(mask,"????????.???")) {
1916 status = check_name(conn, directory);
1917 if (!NT_STATUS_IS_OK(status)) {
1921 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1922 if (dir_hnd == NULL) {
1923 return map_nt_error_from_unix(errno);
1926 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1927 the pattern matches against the long name, otherwise the short name
1928 We don't implement this yet XXXX
1931 status = NT_STATUS_NO_SUCH_FILE;
1933 while ((dname = ReadDirName(dir_hnd, &offset))) {
1936 pstrcpy(fname,dname);
1938 if (!is_visible_file(conn, directory, dname, &st, True)) {
1942 /* Quick check for "." and ".." */
1943 if (fname[0] == '.') {
1944 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1949 if(!mask_match(fname, mask, conn->case_sensitive)) {
1953 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1955 status = check_name(conn, fname);
1956 if (!NT_STATUS_IS_OK(status)) {
1960 status = can_delete(conn, fname, dirtype, can_defer);
1961 if (!NT_STATUS_IS_OK(status)) {
1964 if (SMB_VFS_UNLINK(conn,fname) == 0) {
1966 DEBUG(3,("unlink_internals: succesful unlink "
1968 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1969 FILE_NOTIFY_CHANGE_FILE_NAME,
1977 if (count == 0 && NT_STATUS_IS_OK(status)) {
1978 status = map_nt_error_from_unix(errno);
1984 /****************************************************************************
1986 ****************************************************************************/
1988 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1995 BOOL path_contains_wcard = False;
1997 START_PROFILE(SMBunlink);
1999 dirtype = SVAL(inbuf,smb_vwv0);
2001 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2002 if (!NT_STATUS_IS_OK(status)) {
2003 END_PROFILE(SMBunlink);
2004 return ERROR_NT(status);
2007 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
2009 DEBUG(3,("reply_unlink : %s\n",name));
2011 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2013 if (!NT_STATUS_IS_OK(status)) {
2014 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2015 /* We have re-scheduled this call. */
2018 return ERROR_NT(status);
2021 outsize = set_message(outbuf,0,0,False);
2023 END_PROFILE(SMBunlink);
2027 /****************************************************************************
2029 ****************************************************************************/
2031 static void fail_readraw(void)
2034 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2036 exit_server_cleanly(errstr);
2039 #if defined(WITH_SENDFILE)
2040 /****************************************************************************
2041 Fake (read/write) sendfile. Returns -1 on read or write fail.
2042 ****************************************************************************/
2044 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2048 /* Paranioa check... */
2049 if (nread > bufsize) {
2054 ret = read_file(fsp,buf,startpos,nread);
2060 /* If we had a short read, fill with zeros. */
2062 memset(buf, '\0', nread - ret);
2065 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2069 return (ssize_t)nread;
2073 /****************************************************************************
2074 Use sendfile in readbraw.
2075 ****************************************************************************/
2077 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2078 ssize_t mincount, char *outbuf, int out_buffsize)
2082 #if defined(WITH_SENDFILE)
2084 * We can only use sendfile on a non-chained packet
2085 * but we can use on a non-oplocked file. tridge proved this
2086 * on a train in Germany :-). JRA.
2087 * reply_readbraw has already checked the length.
2090 if ( (chain_size == 0) && (nread > 0) &&
2091 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2094 _smb_setlen(outbuf,nread);
2095 header.data = (uint8 *)outbuf;
2099 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2100 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2101 if (errno == ENOSYS) {
2102 goto normal_readbraw;
2106 * Special hack for broken Linux with no working sendfile. If we
2107 * return EINTR we sent the header but not the rest of the data.
2108 * Fake this up by doing read/write calls.
2110 if (errno == EINTR) {
2111 /* Ensure we don't do this again. */
2112 set_use_sendfile(SNUM(conn), False);
2113 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2115 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2116 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2117 fsp->fsp_name, strerror(errno) ));
2118 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2123 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2124 fsp->fsp_name, strerror(errno) ));
2125 exit_server_cleanly("send_file_readbraw sendfile failed");
2135 ret = read_file(fsp,outbuf+4,startpos,nread);
2136 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2145 _smb_setlen(outbuf,ret);
2146 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2150 /****************************************************************************
2151 Reply to a readbraw (core+ protocol).
2152 ****************************************************************************/
2154 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2156 ssize_t maxcount,mincount;
2159 char *header = outbuf;
2161 START_PROFILE(SMBreadbraw);
2163 if (srv_is_signing_active()) {
2164 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2168 * Special check if an oplock break has been issued
2169 * and the readraw request croses on the wire, we must
2170 * return a zero length response here.
2173 fsp = file_fsp(inbuf,smb_vwv0);
2175 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2177 * fsp could be NULL here so use the value from the packet. JRA.
2179 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2180 _smb_setlen(header,0);
2181 if (write_data(smbd_server_fd(),header,4) != 4)
2183 END_PROFILE(SMBreadbraw);
2187 CHECK_FSP(fsp,conn);
2189 flush_write_cache(fsp, READRAW_FLUSH);
2191 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2192 if(CVAL(inbuf,smb_wct) == 10) {
2194 * This is a large offset (64 bit) read.
2196 #ifdef LARGE_SMB_OFF_T
2198 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2200 #else /* !LARGE_SMB_OFF_T */
2203 * Ensure we haven't been sent a >32 bit offset.
2206 if(IVAL(inbuf,smb_vwv8) != 0) {
2207 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2208 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2209 _smb_setlen(header,0);
2210 if (write_data(smbd_server_fd(),header,4) != 4)
2212 END_PROFILE(SMBreadbraw);
2216 #endif /* LARGE_SMB_OFF_T */
2219 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2220 _smb_setlen(header,0);
2221 if (write_data(smbd_server_fd(),header,4) != 4)
2223 END_PROFILE(SMBreadbraw);
2227 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2228 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2230 /* ensure we don't overrun the packet size */
2231 maxcount = MIN(65535,maxcount);
2233 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2237 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2241 if (startpos >= size) {
2244 nread = MIN(maxcount,(size - startpos));
2248 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2249 if (nread < mincount)
2253 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2254 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2256 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2258 DEBUG(5,("readbraw finished\n"));
2259 END_PROFILE(SMBreadbraw);
2264 #define DBGC_CLASS DBGC_LOCKING
2266 /****************************************************************************
2267 Reply to a lockread (core+ protocol).
2268 ****************************************************************************/
2270 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2278 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2279 struct byte_range_lock *br_lck = NULL;
2280 START_PROFILE(SMBlockread);
2282 CHECK_FSP(fsp,conn);
2283 if (!CHECK_READ(fsp,inbuf)) {
2284 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2287 release_level_2_oplocks_on_change(fsp);
2289 numtoread = SVAL(inbuf,smb_vwv1);
2290 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2292 outsize = set_message(outbuf,5,3,True);
2293 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2294 data = smb_buf(outbuf) + 3;
2297 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2298 * protocol request that predates the read/write lock concept.
2299 * Thus instead of asking for a read lock here we need to ask
2300 * for a write lock. JRA.
2301 * Note that the requested lock size is unaffected by max_recv.
2304 br_lck = do_lock(fsp,
2305 (uint32)SVAL(inbuf,smb_pid),
2306 (SMB_BIG_UINT)numtoread,
2307 (SMB_BIG_UINT)startpos,
2310 False, /* Non-blocking lock. */
2312 TALLOC_FREE(br_lck);
2314 if (NT_STATUS_V(status)) {
2315 END_PROFILE(SMBlockread);
2316 return ERROR_NT(status);
2320 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2323 if (numtoread > max_recv) {
2324 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2325 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2326 (unsigned int)numtoread, (unsigned int)max_recv ));
2327 numtoread = MIN(numtoread,max_recv);
2329 nread = read_file(fsp,data,startpos,numtoread);
2332 END_PROFILE(SMBlockread);
2333 return(UNIXERROR(ERRDOS,ERRnoaccess));
2337 SSVAL(outbuf,smb_vwv0,nread);
2338 SSVAL(outbuf,smb_vwv5,nread+3);
2339 SSVAL(smb_buf(outbuf),1,nread);
2341 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2342 fsp->fnum, (int)numtoread, (int)nread));
2344 END_PROFILE(SMBlockread);
2349 #define DBGC_CLASS DBGC_ALL
2351 /****************************************************************************
2353 ****************************************************************************/
2355 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2362 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2363 START_PROFILE(SMBread);
2365 CHECK_FSP(fsp,conn);
2366 if (!CHECK_READ(fsp,inbuf)) {
2367 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2370 numtoread = SVAL(inbuf,smb_vwv1);
2371 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2373 outsize = set_message(outbuf,5,3,True);
2374 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2376 * The requested read size cannot be greater than max_recv. JRA.
2378 if (numtoread > max_recv) {
2379 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2380 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2381 (unsigned int)numtoread, (unsigned int)max_recv ));
2382 numtoread = MIN(numtoread,max_recv);
2385 data = smb_buf(outbuf) + 3;
2387 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2388 END_PROFILE(SMBread);
2389 return ERROR_DOS(ERRDOS,ERRlock);
2393 nread = read_file(fsp,data,startpos,numtoread);
2396 END_PROFILE(SMBread);
2397 return(UNIXERROR(ERRDOS,ERRnoaccess));
2401 SSVAL(outbuf,smb_vwv0,nread);
2402 SSVAL(outbuf,smb_vwv5,nread+3);
2403 SCVAL(smb_buf(outbuf),0,1);
2404 SSVAL(smb_buf(outbuf),1,nread);
2406 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2407 fsp->fnum, (int)numtoread, (int)nread ) );
2409 END_PROFILE(SMBread);
2413 /****************************************************************************
2414 Reply to a read and X - possibly using sendfile.
2415 ****************************************************************************/
2417 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2418 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2422 char *data = smb_buf(outbuf);
2424 #if defined(WITH_SENDFILE)
2426 * We can only use sendfile on a non-chained packet
2427 * but we can use on a non-oplocked file. tridge proved this
2428 * on a train in Germany :-). JRA.
2431 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2432 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2433 SMB_STRUCT_STAT sbuf;
2436 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2437 return(UNIXERROR(ERRDOS,ERRnoaccess));
2439 if (startpos > sbuf.st_size)
2442 if (smb_maxcnt > (sbuf.st_size - startpos))
2443 smb_maxcnt = (sbuf.st_size - startpos);
2445 if (smb_maxcnt == 0)
2449 * Set up the packet header before send. We
2450 * assume here the sendfile will work (get the
2451 * correct amount of data).
2454 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2455 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2456 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2457 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2458 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2459 SCVAL(outbuf,smb_vwv0,0xFF);
2460 set_message(outbuf,12,smb_maxcnt,False);
2461 header.data = (uint8 *)outbuf;
2462 header.length = data - outbuf;
2465 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2466 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2467 if (errno == ENOSYS) {
2472 * Special hack for broken Linux with no working sendfile. If we
2473 * return EINTR we sent the header but not the rest of the data.
2474 * Fake this up by doing read/write calls.
2477 if (errno == EINTR) {
2478 /* Ensure we don't do this again. */
2479 set_use_sendfile(SNUM(conn), False);
2480 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2482 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2483 len_outbuf - (data-outbuf))) == -1) {
2484 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2485 fsp->fsp_name, strerror(errno) ));
2486 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2488 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2489 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2490 /* Returning -1 here means successful sendfile. */
2494 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2495 fsp->fsp_name, strerror(errno) ));
2496 exit_server_cleanly("send_file_readX sendfile failed");
2499 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2500 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2501 /* Returning -1 here means successful sendfile. */
2509 nread = read_file(fsp,data,startpos,smb_maxcnt);
2512 return(UNIXERROR(ERRDOS,ERRnoaccess));
2515 outsize = set_message(outbuf,12,nread,False);
2516 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2517 SSVAL(outbuf,smb_vwv5,nread);
2518 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2519 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2520 SSVAL(smb_buf(outbuf),-2,nread);
2522 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2523 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2525 /* Returning the number of bytes we want to send back - including header. */
2529 /****************************************************************************
2530 Reply to a read and X.
2531 ****************************************************************************/
2533 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2535 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2536 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2538 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2540 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2543 START_PROFILE(SMBreadX);
2545 /* If it's an IPC, pass off the pipe handler. */
2547 END_PROFILE(SMBreadX);
2548 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2551 CHECK_FSP(fsp,conn);
2552 if (!CHECK_READ(fsp,inbuf)) {
2553 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2556 set_message(outbuf,12,0,True);
2558 if (global_client_caps & CAP_LARGE_READX) {
2559 if (SVAL(inbuf,smb_vwv7) == 1) {
2560 smb_maxcnt |= (1<<16);
2562 if (smb_maxcnt > BUFFER_SIZE) {
2563 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2564 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2565 END_PROFILE(SMBreadX);
2566 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2570 if(CVAL(inbuf,smb_wct) == 12) {
2571 #ifdef LARGE_SMB_OFF_T
2573 * This is a large offset (64 bit) read.
2575 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2577 #else /* !LARGE_SMB_OFF_T */
2580 * Ensure we haven't been sent a >32 bit offset.
2583 if(IVAL(inbuf,smb_vwv10) != 0) {
2584 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2585 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2586 END_PROFILE(SMBreadX);
2587 return ERROR_DOS(ERRDOS,ERRbadaccess);
2590 #endif /* LARGE_SMB_OFF_T */
2594 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2595 END_PROFILE(SMBreadX);
2596 return ERROR_DOS(ERRDOS,ERRlock);
2599 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2600 END_PROFILE(SMBreadX);
2604 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2606 nread = chain_reply(inbuf,outbuf,length,bufsize);
2608 END_PROFILE(SMBreadX);
2612 /****************************************************************************
2613 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2614 ****************************************************************************/
2616 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2619 ssize_t total_written=0;
2620 size_t numtowrite=0;
2625 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2627 START_PROFILE(SMBwritebraw);
2629 if (srv_is_signing_active()) {
2630 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2633 CHECK_FSP(fsp,conn);
2634 if (!CHECK_WRITE(fsp)) {
2635 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2638 tcount = IVAL(inbuf,smb_vwv1);
2639 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2640 write_through = BITSETW(inbuf+smb_vwv7,0);
2642 /* We have to deal with slightly different formats depending
2643 on whether we are using the core+ or lanman1.0 protocol */
2645 if(Protocol <= PROTOCOL_COREPLUS) {
2646 numtowrite = SVAL(smb_buf(inbuf),-2);
2647 data = smb_buf(inbuf);
2649 numtowrite = SVAL(inbuf,smb_vwv10);
2650 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2653 /* force the error type */
2654 SCVAL(inbuf,smb_com,SMBwritec);
2655 SCVAL(outbuf,smb_com,SMBwritec);
2657 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2658 END_PROFILE(SMBwritebraw);
2659 return(ERROR_DOS(ERRDOS,ERRlock));
2663 nwritten = write_file(fsp,data,startpos,numtowrite);
2665 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2666 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2668 if (nwritten < (ssize_t)numtowrite) {
2669 END_PROFILE(SMBwritebraw);
2670 return(UNIXERROR(ERRHRD,ERRdiskfull));
2673 total_written = nwritten;
2675 /* Return a message to the redirector to tell it to send more bytes */
2676 SCVAL(outbuf,smb_com,SMBwritebraw);
2677 SSVALS(outbuf,smb_vwv0,-1);
2678 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2680 if (!send_smb(smbd_server_fd(),outbuf))
2681 exit_server_cleanly("reply_writebraw: send_smb failed.");
2683 /* Now read the raw data into the buffer and write it */
2684 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2685 exit_server_cleanly("secondary writebraw failed");
2688 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2689 numtowrite = smb_len(inbuf);
2691 /* Set up outbuf to return the correct return */
2692 outsize = set_message(outbuf,1,0,True);
2693 SCVAL(outbuf,smb_com,SMBwritec);
2695 if (numtowrite != 0) {
2697 if (numtowrite > BUFFER_SIZE) {
2698 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2699 (unsigned int)numtowrite ));
2700 exit_server_cleanly("secondary writebraw failed");
2703 if (tcount > nwritten+numtowrite) {
2704 DEBUG(3,("Client overestimated the write %d %d %d\n",
2705 (int)tcount,(int)nwritten,(int)numtowrite));
2708 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2709 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2711 exit_server_cleanly("secondary writebraw failed");
2714 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2715 if (nwritten == -1) {
2716 END_PROFILE(SMBwritebraw);
2717 return(UNIXERROR(ERRHRD,ERRdiskfull));
2720 if (nwritten < (ssize_t)numtowrite) {
2721 SCVAL(outbuf,smb_rcls,ERRHRD);
2722 SSVAL(outbuf,smb_err,ERRdiskfull);
2726 total_written += nwritten;
2729 SSVAL(outbuf,smb_vwv0,total_written);
2731 sync_file(conn, fsp, write_through);
2733 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2734 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2736 /* we won't return a status if write through is not selected - this follows what WfWg does */
2737 END_PROFILE(SMBwritebraw);
2738 if (!write_through && total_written==tcount) {
2740 #if RABBIT_PELLET_FIX
2742 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2743 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2745 if (!send_keepalive(smbd_server_fd()))
2746 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2755 #define DBGC_CLASS DBGC_LOCKING
2757 /****************************************************************************
2758 Reply to a writeunlock (core+).
2759 ****************************************************************************/
2761 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2762 int size, int dum_buffsize)
2764 ssize_t nwritten = -1;
2768 NTSTATUS status = NT_STATUS_OK;
2769 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2771 START_PROFILE(SMBwriteunlock);
2773 CHECK_FSP(fsp,conn);
2774 if (!CHECK_WRITE(fsp)) {
2775 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2778 numtowrite = SVAL(inbuf,smb_vwv1);
2779 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2780 data = smb_buf(inbuf) + 3;
2782 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2783 END_PROFILE(SMBwriteunlock);
2784 return ERROR_DOS(ERRDOS,ERRlock);
2787 /* The special X/Open SMB protocol handling of
2788 zero length writes is *NOT* done for
2790 if(numtowrite == 0) {
2793 nwritten = write_file(fsp,data,startpos,numtowrite);
2796 sync_file(conn, fsp, False /* write through */);
2798 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2799 END_PROFILE(SMBwriteunlock);
2800 return(UNIXERROR(ERRHRD,ERRdiskfull));
2804 status = do_unlock(fsp,
2805 (uint32)SVAL(inbuf,smb_pid),
2806 (SMB_BIG_UINT)numtowrite,
2807 (SMB_BIG_UINT)startpos,
2810 if (NT_STATUS_V(status)) {
2811 END_PROFILE(SMBwriteunlock);
2812 return ERROR_NT(status);
2816 outsize = set_message(outbuf,1,0,True);
2818 SSVAL(outbuf,smb_vwv0,nwritten);
2820 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2821 fsp->fnum, (int)numtowrite, (int)nwritten));
2823 END_PROFILE(SMBwriteunlock);
2828 #define DBGC_CLASS DBGC_ALL
2830 /****************************************************************************
2832 ****************************************************************************/
2834 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2837 ssize_t nwritten = -1;
2840 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2842 START_PROFILE(SMBwrite);
2844 /* If it's an IPC, pass off the pipe handler. */
2846 END_PROFILE(SMBwrite);
2847 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2850 CHECK_FSP(fsp,conn);
2851 if (!CHECK_WRITE(fsp)) {
2852 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2855 numtowrite = SVAL(inbuf,smb_vwv1);
2856 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2857 data = smb_buf(inbuf) + 3;
2859 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2860 END_PROFILE(SMBwrite);
2861 return ERROR_DOS(ERRDOS,ERRlock);
2865 * X/Open SMB protocol says that if smb_vwv1 is
2866 * zero then the file size should be extended or
2867 * truncated to the size given in smb_vwv[2-3].
2870 if(numtowrite == 0) {
2872 * This is actually an allocate call, and set EOF. JRA.
2874 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2876 END_PROFILE(SMBwrite);
2877 return ERROR_NT(NT_STATUS_DISK_FULL);
2879 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2881 END_PROFILE(SMBwrite);
2882 return ERROR_NT(NT_STATUS_DISK_FULL);
2885 nwritten = write_file(fsp,data,startpos,numtowrite);
2887 sync_file(conn, fsp, False);
2889 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2890 END_PROFILE(SMBwrite);
2891 return(UNIXERROR(ERRHRD,ERRdiskfull));
2894 outsize = set_message(outbuf,1,0,True);
2896 SSVAL(outbuf,smb_vwv0,nwritten);
2898 if (nwritten < (ssize_t)numtowrite) {
2899 SCVAL(outbuf,smb_rcls,ERRHRD);
2900 SSVAL(outbuf,smb_err,ERRdiskfull);
2903 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2905 END_PROFILE(SMBwrite);
2909 /****************************************************************************
2910 Reply to a write and X.
2911 ****************************************************************************/
2913 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2915 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2916 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2917 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2918 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2919 ssize_t nwritten = -1;
2920 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2921 unsigned int smblen = smb_len(inbuf);
2923 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2924 START_PROFILE(SMBwriteX);
2926 /* If it's an IPC, pass off the pipe handler. */
2928 END_PROFILE(SMBwriteX);
2929 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2932 CHECK_FSP(fsp,conn);
2933 if (!CHECK_WRITE(fsp)) {
2934 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2937 set_message(outbuf,6,0,True);
2939 /* Deal with possible LARGE_WRITEX */
2941 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2944 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2945 END_PROFILE(SMBwriteX);
2946 return ERROR_DOS(ERRDOS,ERRbadmem);
2949 data = smb_base(inbuf) + smb_doff;
2951 if(CVAL(inbuf,smb_wct) == 14) {
2952 #ifdef LARGE_SMB_OFF_T
2954 * This is a large offset (64 bit) write.
2956 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2958 #else /* !LARGE_SMB_OFF_T */
2961 * Ensure we haven't been sent a >32 bit offset.
2964 if(IVAL(inbuf,smb_vwv12) != 0) {
2965 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2966 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2967 END_PROFILE(SMBwriteX);
2968 return ERROR_DOS(ERRDOS,ERRbadaccess);
2971 #endif /* LARGE_SMB_OFF_T */
2974 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2975 END_PROFILE(SMBwriteX);
2976 return ERROR_DOS(ERRDOS,ERRlock);
2979 /* X/Open SMB protocol says that, unlike SMBwrite
2980 if the length is zero then NO truncation is
2981 done, just a write of zero. To truncate a file,
2984 if(numtowrite == 0) {
2988 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2989 fsp,data,startpos,numtowrite)) {
2990 END_PROFILE(SMBwriteX);
2994 nwritten = write_file(fsp,data,startpos,numtowrite);
2997 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2998 END_PROFILE(SMBwriteX);
2999 return(UNIXERROR(ERRHRD,ERRdiskfull));
3002 SSVAL(outbuf,smb_vwv2,nwritten);
3004 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3006 if (nwritten < (ssize_t)numtowrite) {
3007 SCVAL(outbuf,smb_rcls,ERRHRD);
3008 SSVAL(outbuf,smb_err,ERRdiskfull);
3011 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3012 fsp->fnum, (int)numtowrite, (int)nwritten));
3014 sync_file(conn, fsp, write_through);
3016 END_PROFILE(SMBwriteX);
3017 return chain_reply(inbuf,outbuf,length,bufsize);
3020 /****************************************************************************
3022 ****************************************************************************/
3024 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3030 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3031 START_PROFILE(SMBlseek);
3033 CHECK_FSP(fsp,conn);
3035 flush_write_cache(fsp, SEEK_FLUSH);
3037 mode = SVAL(inbuf,smb_vwv1) & 3;
3038 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3039 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3048 res = fsp->fh->pos + startpos;
3059 if (umode == SEEK_END) {
3060 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3061 if(errno == EINVAL) {
3062 SMB_OFF_T current_pos = startpos;
3063 SMB_STRUCT_STAT sbuf;
3065 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3066 END_PROFILE(SMBlseek);
3067 return(UNIXERROR(ERRDOS,ERRnoaccess));
3070 current_pos += sbuf.st_size;
3072 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3077 END_PROFILE(SMBlseek);
3078 return(UNIXERROR(ERRDOS,ERRnoaccess));
3084 outsize = set_message(outbuf,2,0,True);
3085 SIVAL(outbuf,smb_vwv0,res);
3087 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3088 fsp->fnum, (double)startpos, (double)res, mode));
3090 END_PROFILE(SMBlseek);
3094 /****************************************************************************
3096 ****************************************************************************/
3098 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3100 int outsize = set_message(outbuf,0,0,False);
3101 uint16 fnum = SVAL(inbuf,smb_vwv0);
3102 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3103 START_PROFILE(SMBflush);
3106 CHECK_FSP(fsp,conn);
3109 file_sync_all(conn);
3111 sync_file(conn,fsp, True);
3114 DEBUG(3,("flush\n"));
3115 END_PROFILE(SMBflush);
3119 /****************************************************************************
3121 conn POINTER CAN BE NULL HERE !
3122 ****************************************************************************/
3124 int reply_exit(connection_struct *conn,
3125 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3128 START_PROFILE(SMBexit);
3130 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3132 outsize = set_message(outbuf,0,0,False);
3134 DEBUG(3,("exit\n"));
3136 END_PROFILE(SMBexit);
3140 /****************************************************************************
3141 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3142 ****************************************************************************/
3144 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3147 NTSTATUS status = NT_STATUS_OK;
3149 files_struct *fsp = NULL;
3150 START_PROFILE(SMBclose);
3152 outsize = set_message(outbuf,0,0,False);
3154 /* If it's an IPC, pass off to the pipe handler. */
3156 END_PROFILE(SMBclose);
3157 return reply_pipe_close(conn, inbuf,outbuf);
3160 fsp = file_fsp(inbuf,smb_vwv0);
3163 * We can only use CHECK_FSP if we know it's not a directory.
3166 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3167 END_PROFILE(SMBclose);
3168 return ERROR_DOS(ERRDOS,ERRbadfid);
3171 if(fsp->is_directory) {
3173 * Special case - close NT SMB directory handle.
3175 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3176 status = close_file(fsp,NORMAL_CLOSE);
3179 * Close ordinary file.
3182 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3183 fsp->fh->fd, fsp->fnum,
3184 conn->num_files_open));
3187 * Take care of any time sent in the close.
3190 fsp_set_pending_modtime(fsp,
3191 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3194 * close_file() returns the unix errno if an error
3195 * was detected on close - normally this is due to
3196 * a disk full error. If not then it was probably an I/O error.
3199 status = close_file(fsp,NORMAL_CLOSE);
3202 if(!NT_STATUS_IS_OK(status)) {
3203 END_PROFILE(SMBclose);
3204 return ERROR_NT(status);
3207 END_PROFILE(SMBclose);
3211 /****************************************************************************
3212 Reply to a writeclose (Core+ protocol).
3213 ****************************************************************************/
3215 int reply_writeclose(connection_struct *conn,
3216 char *inbuf,char *outbuf, int size, int dum_buffsize)
3219 ssize_t nwritten = -1;
3221 NTSTATUS close_status = NT_STATUS_OK;
3224 struct timespec mtime;
3225 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3226 START_PROFILE(SMBwriteclose);
3228 CHECK_FSP(fsp,conn);
3229 if (!CHECK_WRITE(fsp)) {
3230 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3233 numtowrite = SVAL(inbuf,smb_vwv1);
3234 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3235 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3236 data = smb_buf(inbuf) + 1;
3238 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3239 END_PROFILE(SMBwriteclose);
3240 return ERROR_DOS(ERRDOS,ERRlock);
3243 nwritten = write_file(fsp,data,startpos,numtowrite);
3245 set_filetime(conn, fsp->fsp_name, mtime);
3248 * More insanity. W2K only closes the file if writelen > 0.
3253 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3255 close_status = close_file(fsp,NORMAL_CLOSE);
3258 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3259 fsp->fnum, (int)numtowrite, (int)nwritten,
3260 conn->num_files_open));
3262 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3263 END_PROFILE(SMBwriteclose);
3264 return(UNIXERROR(ERRHRD,ERRdiskfull));
3267 if(!NT_STATUS_IS_OK(close_status)) {
3268 END_PROFILE(SMBwriteclose);
3269 return ERROR_NT(close_status);
3272 outsize = set_message(outbuf,1,0,True);
3274 SSVAL(outbuf,smb_vwv0,nwritten);
3275 END_PROFILE(SMBwriteclose);
3280 #define DBGC_CLASS DBGC_LOCKING
3282 /****************************************************************************
3284 ****************************************************************************/
3286 int reply_lock(connection_struct *conn,
3287 char *inbuf,char *outbuf, int length, int dum_buffsize)
3289 int outsize = set_message(outbuf,0,0,False);
3290 SMB_BIG_UINT count,offset;
3292 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3293 struct byte_range_lock *br_lck = NULL;
3295 START_PROFILE(SMBlock);
3297 CHECK_FSP(fsp,conn);
3299 release_level_2_oplocks_on_change(fsp);
3301 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3302 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3304 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3305 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3307 br_lck = do_lock(fsp,
3308 (uint32)SVAL(inbuf,smb_pid),
3313 False, /* Non-blocking lock. */
3316 TALLOC_FREE(br_lck);
3318 if (NT_STATUS_V(status)) {
3319 END_PROFILE(SMBlock);
3320 return ERROR_NT(status);
3323 END_PROFILE(SMBlock);
3327 /****************************************************************************
3329 ****************************************************************************/
3331 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3334 int outsize = set_message(outbuf,0,0,False);
3335 SMB_BIG_UINT count,offset;
3337 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3338 START_PROFILE(SMBunlock);
3340 CHECK_FSP(fsp,conn);
3342 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3343 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3345 status = do_unlock(fsp,
3346 (uint32)SVAL(inbuf,smb_pid),
3351 if (NT_STATUS_V(status)) {
3352 END_PROFILE(SMBunlock);
3353 return ERROR_NT(status);
3356 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3357 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3359 END_PROFILE(SMBunlock);
3364 #define DBGC_CLASS DBGC_ALL
3366 /****************************************************************************
3368 conn POINTER CAN BE NULL HERE !
3369 ****************************************************************************/
3371 int reply_tdis(connection_struct *conn,
3372 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3374 int outsize = set_message(outbuf,0,0,False);
3376 START_PROFILE(SMBtdis);
3378 vuid = SVAL(inbuf,smb_uid);
3381 DEBUG(4,("Invalid connection in tdis\n"));
3382 END_PROFILE(SMBtdis);
3383 return ERROR_DOS(ERRSRV,ERRinvnid);
3388 close_cnum(conn,vuid);
3390 END_PROFILE(SMBtdis);
3394 /****************************************************************************
3396 conn POINTER CAN BE NULL HERE !
3397 ****************************************************************************/
3399 int reply_echo(connection_struct *conn,
3400 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3402 int smb_reverb = SVAL(inbuf,smb_vwv0);
3404 unsigned int data_len = smb_buflen(inbuf);
3405 int outsize = set_message(outbuf,1,data_len,True);
3406 START_PROFILE(SMBecho);
3408 if (data_len > BUFFER_SIZE) {
3409 DEBUG(0,("reply_echo: data_len too large.\n"));
3410 END_PROFILE(SMBecho);
3414 /* copy any incoming data back out */
3416 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3418 if (smb_reverb > 100) {
3419 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3423 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3424 SSVAL(outbuf,smb_vwv0,seq_num);
3426 smb_setlen(outbuf,outsize - 4);
3429 if (!send_smb(smbd_server_fd(),outbuf))
3430 exit_server_cleanly("reply_echo: send_smb failed.");
3433 DEBUG(3,("echo %d times\n", smb_reverb));
3437 END_PROFILE(SMBecho);
3441 /****************************************************************************
3442 Reply to a printopen.
3443 ****************************************************************************/
3445 int reply_printopen(connection_struct *conn,
3446 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3452 START_PROFILE(SMBsplopen);
3454 if (!CAN_PRINT(conn)) {
3455 END_PROFILE(SMBsplopen);
3456 return ERROR_DOS(ERRDOS,ERRnoaccess);
3459 /* Open for exclusive use, write only. */
3460 status = print_fsp_open(conn, NULL, &fsp);
3462 if (!NT_STATUS_IS_OK(status)) {
3463 END_PROFILE(SMBsplopen);
3464 return(ERROR_NT(status));
3467 outsize = set_message(outbuf,1,0,True);
3468 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3470 DEBUG(3,("openprint fd=%d fnum=%d\n",
3471 fsp->fh->fd, fsp->fnum));
3473 END_PROFILE(SMBsplopen);
3477 /****************************************************************************
3478 Reply to a printclose.
3479 ****************************************************************************/
3481 int reply_printclose(connection_struct *conn,
3482 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3484 int outsize = set_message(outbuf,0,0,False);
3485 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3487 START_PROFILE(SMBsplclose);
3489 CHECK_FSP(fsp,conn);
3491 if (!CAN_PRINT(conn)) {
3492 END_PROFILE(SMBsplclose);
3493 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3496 DEBUG(3,("printclose fd=%d fnum=%d\n",
3497 fsp->fh->fd,fsp->fnum));
3499 status = close_file(fsp,NORMAL_CLOSE);
3501 if(!NT_STATUS_IS_OK(status)) {
3502 END_PROFILE(SMBsplclose);
3503 return ERROR_NT(status);
3506 END_PROFILE(SMBsplclose);
3510 /****************************************************************************
3511 Reply to a printqueue.
3512 ****************************************************************************/
3514 int reply_printqueue(connection_struct *conn,
3515 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3517 int outsize = set_message(outbuf,2,3,True);
3518 int max_count = SVAL(inbuf,smb_vwv0);
3519 int start_index = SVAL(inbuf,smb_vwv1);
3520 START_PROFILE(SMBsplretq);
3522 /* we used to allow the client to get the cnum wrong, but that
3523 is really quite gross and only worked when there was only
3524 one printer - I think we should now only accept it if they
3525 get it right (tridge) */
3526 if (!CAN_PRINT(conn)) {
3527 END_PROFILE(SMBsplretq);
3528 return ERROR_DOS(ERRDOS,ERRnoaccess);
3531 SSVAL(outbuf,smb_vwv0,0);
3532 SSVAL(outbuf,smb_vwv1,0);
3533 SCVAL(smb_buf(outbuf),0,1);
3534 SSVAL(smb_buf(outbuf),1,0);
3536 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3537 start_index, max_count));
3540 print_queue_struct *queue = NULL;
3541 print_status_struct status;
3542 char *p = smb_buf(outbuf) + 3;
3543 int count = print_queue_status(SNUM(conn), &queue, &status);
3544 int num_to_get = ABS(max_count);
3545 int first = (max_count>0?start_index:start_index+max_count+1);
3551 num_to_get = MIN(num_to_get,count-first);
3554 for (i=first;i<first+num_to_get;i++) {
3555 srv_put_dos_date2(p,0,queue[i].time);
3556 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3557 SSVAL(p,5, queue[i].job);
3558 SIVAL(p,7,queue[i].size);
3560 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3565 outsize = set_message(outbuf,2,28*count+3,False);
3566 SSVAL(outbuf,smb_vwv0,count);
3567 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3568 SCVAL(smb_buf(outbuf),0,1);
3569 SSVAL(smb_buf(outbuf),1,28*count);
3574 DEBUG(3,("%d entries returned in queue\n",count));
3577 END_PROFILE(SMBsplretq);
3581 /****************************************************************************
3582 Reply to a printwrite.
3583 ****************************************************************************/
3585 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3588 int outsize = set_message(outbuf,0,0,False);
3590 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3592 START_PROFILE(SMBsplwr);
3594 if (!CAN_PRINT(conn)) {
3595 END_PROFILE(SMBsplwr);
3596 return ERROR_DOS(ERRDOS,ERRnoaccess);
3599 CHECK_FSP(fsp,conn);
3600 if (!CHECK_WRITE(fsp)) {
3601 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3604 numtowrite = SVAL(smb_buf(inbuf),1);
3605 data = smb_buf(inbuf) + 3;
3607 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3608 END_PROFILE(SMBsplwr);
3609 return(UNIXERROR(ERRHRD,ERRdiskfull));
3612 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3614 END_PROFILE(SMBsplwr);
3618 /****************************************************************************
3620 ****************************************************************************/
3622 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3627 SMB_STRUCT_STAT sbuf;
3629 START_PROFILE(SMBmkdir);
3631 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3632 if (!NT_STATUS_IS_OK(status)) {
3633 END_PROFILE(SMBmkdir);
3634 return ERROR_NT(status);
3637 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3639 status = unix_convert(conn, directory, False, NULL, &sbuf);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 END_PROFILE(SMBmkdir);
3642 return ERROR_NT(status);
3645 status = check_name(conn, directory);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 END_PROFILE(SMBmkdir);
3648 return ERROR_NT(status);
3651 status = create_directory(conn, directory);
3653 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3655 if (!NT_STATUS_IS_OK(status)) {
3657 if (!use_nt_status()
3658 && NT_STATUS_EQUAL(status,
3659 NT_STATUS_OBJECT_NAME_COLLISION)) {
3661 * Yes, in the DOS error code case we get a
3662 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3663 * samba4 torture test.
3665 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3668 END_PROFILE(SMBmkdir);
3669 return ERROR_NT(status);
3672 outsize = set_message(outbuf,0,0,False);
3674 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3676 END_PROFILE(SMBmkdir);
3680 /****************************************************************************
3681 Static function used by reply_rmdir to delete an entire directory
3682 tree recursively. Return True on ok, False on fail.
3683 ****************************************************************************/
3685 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3687 const char *dname = NULL;
3690 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3695 while((dname = ReadDirName(dir_hnd, &offset))) {
3699 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3702 if (!is_visible_file(conn, directory, dname, &st, False))
3705 /* Construct the full name. */
3706 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3712 pstrcpy(fullname, directory);
3713 pstrcat(fullname, "/");
3714 pstrcat(fullname, dname);
3716 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3721 if(st.st_mode & S_IFDIR) {
3722 if(!recursive_rmdir(conn, fullname)) {
3726 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3730 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3739 /****************************************************************************
3740 The internals of the rmdir code - called elsewhere.
3741 ****************************************************************************/
3743 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3748 ret = SMB_VFS_RMDIR(conn,directory);
3750 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3751 FILE_NOTIFY_CHANGE_DIR_NAME,
3753 return NT_STATUS_OK;
3756 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3758 * Check to see if the only thing in this directory are
3759 * vetoed files/directories. If so then delete them and
3760 * retry. If we fail to delete any of them (and we *don't*
3761 * do a recursive delete) then fail the rmdir.
3765 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3767 if(dir_hnd == NULL) {
3772 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3773 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3775 if (!is_visible_file(conn, directory, dname, &st, False))
3777 if(!IS_VETO_PATH(conn, dname)) {
3784 /* We only have veto files/directories. Recursive delete. */
3786 RewindDir(dir_hnd,&dirpos);
3787 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3790 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3792 if (!is_visible_file(conn, directory, dname, &st, False))
3795 /* Construct the full name. */
3796 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3801 pstrcpy(fullname, directory);
3802 pstrcat(fullname, "/");
3803 pstrcat(fullname, dname);
3805 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3807 if(st.st_mode & S_IFDIR) {
3808 if(lp_recursive_veto_delete(SNUM(conn))) {
3809 if(!recursive_rmdir(conn, fullname))
3812 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3814 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3818 /* Retry the rmdir */
3819 ret = SMB_VFS_RMDIR(conn,directory);
3825 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3826 "%s\n", directory,strerror(errno)));
3827 return map_nt_error_from_unix(errno);
3830 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3831 FILE_NOTIFY_CHANGE_DIR_NAME,
3834 return NT_STATUS_OK;
3837 /****************************************************************************
3839 ****************************************************************************/
3841 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3845 SMB_STRUCT_STAT sbuf;
3847 START_PROFILE(SMBrmdir);
3849 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3850 if (!NT_STATUS_IS_OK(status)) {
3851 END_PROFILE(SMBrmdir);
3852 return ERROR_NT(status);
3855 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3857 status = unix_convert(conn, directory, False, NULL, &sbuf);
3858 if (!NT_STATUS_IS_OK(status)) {
3859 END_PROFILE(SMBrmdir);
3860 return ERROR_NT(status);
3863 status = check_name(conn, directory);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 END_PROFILE(SMBrmdir);
3866 return ERROR_NT(status);
3869 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3870 status = rmdir_internals(conn, directory);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 END_PROFILE(SMBrmdir);
3873 return ERROR_NT(status);
3876 outsize = set_message(outbuf,0,0,False);
3878 DEBUG( 3, ( "rmdir %s\n", directory ) );
3880 END_PROFILE(SMBrmdir);
3884 /*******************************************************************
3885 Resolve wildcards in a filename rename.
3886 Note that name is in UNIX charset and thus potentially can be more
3887 than fstring buffer (255 bytes) especially in default UTF-8 case.
3888 Therefore, we use pstring inside and all calls should ensure that
3889 name2 is at least pstring-long (they do already)
3890 ********************************************************************/
3892 static BOOL resolve_wildcards(const char *name1, char *name2)
3894 pstring root1,root2;
3896 char *p,*p2, *pname1, *pname2;
3897 int available_space, actual_space;
3899 pname1 = strrchr_m(name1,'/');
3900 pname2 = strrchr_m(name2,'/');
3902 if (!pname1 || !pname2)
3905 pstrcpy(root1,pname1);
3906 pstrcpy(root2,pname2);
3907 p = strrchr_m(root1,'.');
3914 p = strrchr_m(root2,'.');
3928 } else if (*p2 == '*') {
3944 } else if (*p2 == '*') {
3954 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3957 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3958 if (actual_space >= available_space - 1) {
3959 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3960 actual_space - available_space));
3963 pstrcpy_base(pname2, root2, name2);
3969 /****************************************************************************
3970 Ensure open files have their names updated. Updated to notify other smbd's
3972 ****************************************************************************/
3974 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
3975 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
3978 BOOL did_rename = False;
3980 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3981 /* fsp_name is a relative path under the fsp. To change this for other
3982 sharepaths we need to manipulate relative paths. */
3983 /* TODO - create the absolute path and manipulate the newname
3984 relative to the sharepath. */
3985 if (fsp->conn != conn) {
3988 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3989 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3990 fsp->fsp_name, newname ));
3991 string_set(&fsp->fsp_name, newname);
3996 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3997 (unsigned int)dev, (double)inode, newname ));
4000 /* Send messages to all smbd's (not ourself) that the name has changed. */
4001 rename_share_filename(lck, conn->connectpath, newname);
4004 /****************************************************************************
4005 We need to check if the source path is a parent directory of the destination
4006 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4007 refuse the rename with a sharing violation. Under UNIX the above call can
4008 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4009 probably need to check that the client is a Windows one before disallowing
4010 this as a UNIX client (one with UNIX extensions) can know the source is a
4011 symlink and make this decision intelligently. Found by an excellent bug
4012 report from <AndyLiebman@aol.com>.
4013 ****************************************************************************/
4015 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4017 const char *psrc = src;
4018 const char *pdst = dest;
4021 if (psrc[0] == '.' && psrc[1] == '/') {
4024 if (pdst[0] == '.' && pdst[1] == '/') {
4027 if ((slen = strlen(psrc)) > strlen(pdst)) {
4030 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4033 /****************************************************************************
4034 Rename an open file - given an fsp.
4035 ****************************************************************************/
4037 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4039 SMB_STRUCT_STAT sbuf;
4040 pstring newname_last_component;
4041 NTSTATUS status = NT_STATUS_OK;
4043 struct share_mode_lock *lck = NULL;
4047 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4048 if (!NT_STATUS_IS_OK(status)) {
4052 status = check_name(conn, newname);
4053 if (!NT_STATUS_IS_OK(status)) {
4057 /* Ensure newname contains a '/' */
4058 if(strrchr_m(newname,'/') == 0) {
4061 pstrcpy(tmpstr, "./");
4062 pstrcat(tmpstr, newname);
4063 pstrcpy(newname, tmpstr);
4067 * Check for special case with case preserving and not
4068 * case sensitive. If the old last component differs from the original
4069 * last component only by case, then we should allow
4070 * the rename (user is trying to change the case of the
4074 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4075 strequal(newname, fsp->fsp_name)) {
4077 pstring newname_modified_last_component;
4080 * Get the last component of the modified name.
4081 * Note that we guarantee that newname contains a '/'
4084 p = strrchr_m(newname,'/');
4085 pstrcpy(newname_modified_last_component,p+1);
4087 if(strcsequal(newname_modified_last_component,
4088 newname_last_component) == False) {
4090 * Replace the modified last component with
4093 pstrcpy(p+1, newname_last_component);
4098 * If the src and dest names are identical - including case,
4099 * don't do the rename, just return success.
4102 if (strcsequal(fsp->fsp_name, newname)) {
4103 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4105 return NT_STATUS_OK;
4108 dest_exists = vfs_object_exist(conn,newname,NULL);
4110 if(!replace_if_exists && dest_exists) {
4111 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4112 fsp->fsp_name,newname));
4113 return NT_STATUS_OBJECT_NAME_COLLISION;
4116 status = can_rename(conn,newname,attrs,&sbuf);
4118 if (dest_exists && !NT_STATUS_IS_OK(status)) {
4119 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4120 nt_errstr(status), fsp->fsp_name,newname));
4121 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4122 status = NT_STATUS_ACCESS_DENIED;
4126 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4127 return NT_STATUS_ACCESS_DENIED;
4130 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4132 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4133 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4134 fsp->fsp_name,newname));
4135 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4137 return NT_STATUS_OK;
4142 if (errno == ENOTDIR || errno == EISDIR) {
4143 status = NT_STATUS_OBJECT_NAME_COLLISION;
4145 status = map_nt_error_from_unix(errno);
4148 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4149 nt_errstr(status), fsp->fsp_name,newname));
4155 * Do the notify calls from a rename
4158 static void notify_rename(connection_struct *conn, BOOL is_dir,
4159 const char *oldpath, const char *newpath)
4161 char *olddir, *newdir;
4162 const char *oldname, *newname;
4165 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4166 : FILE_NOTIFY_CHANGE_FILE_NAME;
4168 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4169 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4170 TALLOC_FREE(olddir);
4174 if (strcmp(olddir, newdir) == 0) {
4175 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4176 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4179 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4180 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4182 TALLOC_FREE(olddir);
4183 TALLOC_FREE(newdir);
4185 /* this is a strange one. w2k3 gives an additional event for
4186 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4187 files, but not directories */
4189 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4190 FILE_NOTIFY_CHANGE_ATTRIBUTES
4191 |FILE_NOTIFY_CHANGE_CREATION,
4196 /****************************************************************************
4197 The guts of the rename command, split out so it may be called by the NT SMB
4199 ****************************************************************************/
4201 NTSTATUS rename_internals(connection_struct *conn,
4205 BOOL replace_if_exists,
4211 pstring last_component_src;
4212 pstring last_component_dest;
4215 NTSTATUS status = NT_STATUS_OK;
4216 SMB_STRUCT_STAT sbuf1, sbuf2;
4217 struct share_mode_lock *lck = NULL;
4218 struct smb_Dir *dir_hnd = NULL;
4223 *directory = *mask = 0;
4228 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4229 if (!NT_STATUS_IS_OK(status)) {
4233 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4234 if (!NT_STATUS_IS_OK(status)) {
4239 * Split the old name into directory and last component
4240 * strings. Note that unix_convert may have stripped off a
4241 * leading ./ from both name and newname if the rename is
4242 * at the root of the share. We need to make sure either both
4243 * name and newname contain a / character or neither of them do
4244 * as this is checked in resolve_wildcards().
4247 p = strrchr_m(name,'/');
4249 pstrcpy(directory,".");
4253 pstrcpy(directory,name);
4255 *p = '/'; /* Replace needed for exceptional test below. */
4259 * We should only check the mangled cache
4260 * here if unix_convert failed. This means
4261 * that the path in 'mask' doesn't exist
4262 * on the file system and so we need to look
4263 * for a possible mangle. This patch from
4264 * Tine Smukavec <valentin.smukavec@hermes.si>.
4267 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4268 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4271 if (!src_has_wild) {
4273 * No wildcards - just process the one file.
4275 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4277 /* Add a terminating '/' to the directory name. */
4278 pstrcat(directory,"/");
4279 pstrcat(directory,mask);
4281 /* Ensure newname contains a '/' also */
4282 if(strrchr_m(newname,'/') == 0) {
4285 pstrcpy(tmpstr, "./");
4286 pstrcat(tmpstr, newname);
4287 pstrcpy(newname, tmpstr);
4290 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4291 "case_preserve = %d, short case preserve = %d, "
4292 "directory = %s, newname = %s, "
4293 "last_component_dest = %s, is_8_3 = %d\n",
4294 conn->case_sensitive, conn->case_preserve,
4295 conn->short_case_preserve, directory,
4296 newname, last_component_dest, is_short_name));
4298 /* Ensure the source name is valid for us to access. */
4299 status = check_name(conn, directory);
4300 if (!NT_STATUS_IS_OK(status)) {
4304 /* The dest name still may have wildcards. */
4305 if (dest_has_wild) {
4306 if (!resolve_wildcards(directory,newname)) {
4307 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4308 directory,newname));
4309 return NT_STATUS_NO_MEMORY;
4314 * Check for special case with case preserving and not
4315 * case sensitive, if directory and newname are identical,
4316 * and the old last component differs from the original
4317 * last component only by case, then we should allow
4318 * the rename (user is trying to change the case of the
4321 if((conn->case_sensitive == False) &&
4322 (((conn->case_preserve == True) &&
4323 (is_short_name == False)) ||
4324 ((conn->short_case_preserve == True) &&
4325 (is_short_name == True))) &&
4326 strcsequal(directory, newname)) {
4327 pstring modified_last_component;
4330 * Get the last component of the modified name.
4331 * Note that we guarantee that newname contains a '/'
4334 p = strrchr_m(newname,'/');
4335 pstrcpy(modified_last_component,p+1);
4337 if(strcsequal(modified_last_component,
4338 last_component_dest) == False) {
4340 * Replace the modified last component with
4343 pstrcpy(p+1, last_component_dest);
4347 /* Ensure the dest name is valid for us to access. */
4348 status = check_name(conn, newname);
4349 if (!NT_STATUS_IS_OK(status)) {
4354 * The source object must exist.
4357 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4358 DEBUG(3, ("rename_internals: source doesn't exist "
4359 "doing rename %s -> %s\n",
4360 directory,newname));
4362 if (errno == ENOTDIR || errno == EISDIR
4363 || errno == ENOENT) {
4365 * Must return different errors depending on
4366 * whether the parent directory existed or
4370 p = strrchr_m(directory, '/');
4372 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4374 if (vfs_object_exist(conn, directory, NULL))
4375 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4376 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4378 status = map_nt_error_from_unix(errno);
4379 DEBUG(3, ("rename_internals: Error %s rename %s -> "
4380 "%s\n", nt_errstr(status), directory,
4386 status = can_rename(conn,directory,attrs,&sbuf1);
4388 if (!NT_STATUS_IS_OK(status)) {
4389 DEBUG(3,("rename_internals: Error %s rename %s -> "
4390 "%s\n", nt_errstr(status), directory,
4396 * If the src and dest names are identical - including case,
4397 * don't do the rename, just return success.
4400 if (strcsequal(directory, newname)) {
4401 rename_open_files(conn, NULL, sbuf1.st_dev,
4402 sbuf1.st_ino, newname);
4403 DEBUG(3, ("rename_internals: identical names in "
4404 "rename %s - returning success\n",
4406 return NT_STATUS_OK;
4409 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4410 DEBUG(3,("rename_internals: dest exists doing "
4411 "rename %s -> %s\n", directory, newname));
4412 return NT_STATUS_OBJECT_NAME_COLLISION;
4415 if (rename_path_prefix_equal(directory, newname)) {
4416 return NT_STATUS_SHARING_VIOLATION;
4419 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4422 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4423 DEBUG(3,("rename_internals: succeeded doing rename "
4424 "on %s -> %s\n", directory, newname));
4425 rename_open_files(conn, lck, sbuf1.st_dev,
4426 sbuf1.st_ino, newname);
4428 notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4429 directory, newname);
4430 return NT_STATUS_OK;
4434 if (errno == ENOTDIR || errno == EISDIR) {
4435 status = NT_STATUS_OBJECT_NAME_COLLISION;
4437 status = map_nt_error_from_unix(errno);
4440 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4441 nt_errstr(status), directory,newname));
4447 * Wildcards - process each file that matches.
4449 if (strequal(mask,"????????.???")) {
4453 status = check_name(conn, directory);
4454 if (!NT_STATUS_IS_OK(status)) {
4458 dir_hnd = OpenDir(conn, directory, mask, attrs);
4459 if (dir_hnd == NULL) {
4460 return map_nt_error_from_unix(errno);
4463 status = NT_STATUS_NO_SUCH_FILE;
4465 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4466 * - gentest fix. JRA
4469 while ((dname = ReadDirName(dir_hnd, &offset))) {
4471 BOOL sysdir_entry = False;
4473 pstrcpy(fname,dname);
4475 /* Quick check for "." and ".." */
4476 if (fname[0] == '.') {
4477 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4479 sysdir_entry = True;
4486 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4490 if(!mask_match(fname, mask, conn->case_sensitive)) {
4495 status = NT_STATUS_OBJECT_NAME_INVALID;
4499 status = NT_STATUS_ACCESS_DENIED;
4500 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4502 /* Ensure the source name is valid for us to access. */
4503 status = check_name(conn, fname);
4504 if (!NT_STATUS_IS_OK(status)) {
4508 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4509 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4510 DEBUG(6, ("rename %s failed. Error %s\n",
4511 fname, nt_errstr(status)));
4514 status = can_rename(conn,fname,attrs,&sbuf1);
4515 if (!NT_STATUS_IS_OK(status)) {
4516 DEBUG(6, ("rename %s refused\n", fname));
4519 pstrcpy(destname,newname);
4521 if (!resolve_wildcards(fname,destname)) {
4522 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4527 /* Ensure the dest name is valid for us to access. */
4528 status = check_name(conn, destname);
4529 if (!NT_STATUS_IS_OK(status)) {
4533 if (strcsequal(fname,destname)) {
4534 rename_open_files(conn, NULL, sbuf1.st_dev,
4535 sbuf1.st_ino, newname);
4536 DEBUG(3,("rename_internals: identical names "
4537 "in wildcard rename %s - success\n",
4540 status = NT_STATUS_OK;
4544 if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
4545 DEBUG(6,("file_exist %s\n", destname));
4546 status = NT_STATUS_OBJECT_NAME_COLLISION;
4550 if (rename_path_prefix_equal(fname, destname)) {
4551 return NT_STATUS_SHARING_VIOLATION;
4554 lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4555 sbuf1.st_ino, NULL, NULL);
4557 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4558 rename_open_files(conn, lck, sbuf1.st_dev,
4559 sbuf1.st_ino, newname);
4561 status = NT_STATUS_OK;
4564 DEBUG(3,("rename_internals: doing rename on %s -> "
4565 "%s\n",fname,destname));
4569 if (count == 0 && NT_STATUS_IS_OK(status)) {
4570 status = map_nt_error_from_unix(errno);
4576 /****************************************************************************
4578 ****************************************************************************/
4580 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4587 uint32 attrs = SVAL(inbuf,smb_vwv0);
4589 BOOL src_has_wcard = False;
4590 BOOL dest_has_wcard = False;
4592 START_PROFILE(SMBmv);
4594 p = smb_buf(inbuf) + 1;
4595 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
4596 if (!NT_STATUS_IS_OK(status)) {
4598 return ERROR_NT(status);
4601 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
4602 if (!NT_STATUS_IS_OK(status)) {
4604 return ERROR_NT(status);
4607 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4608 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4610 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4612 status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
4613 if (!NT_STATUS_IS_OK(status)) {
4615 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4616 /* We have re-scheduled this call. */
4619 return ERROR_NT(status);
4622 outsize = set_message(outbuf,0,0,False);
4628 /*******************************************************************
4629 Copy a file as part of a reply_copy.
4630 ******************************************************************/
4633 * TODO: check error codes on all callers
4636 NTSTATUS copy_file(connection_struct *conn,
4641 BOOL target_is_directory)
4643 SMB_STRUCT_STAT src_sbuf, sbuf2;
4645 files_struct *fsp1,*fsp2;
4648 uint32 new_create_disposition;
4651 pstrcpy(dest,dest1);
4652 if (target_is_directory) {
4653 char *p = strrchr_m(src,'/');
4663 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4664 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4667 if (!target_is_directory && count) {
4668 new_create_disposition = FILE_OPEN;
4670 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4671 NULL, NULL, &new_create_disposition, NULL)) {
4672 return NT_STATUS_INVALID_PARAMETER;
4676 status = open_file_ntcreate(conn,src,&src_sbuf,
4678 FILE_SHARE_READ|FILE_SHARE_WRITE,
4681 FILE_ATTRIBUTE_NORMAL,
4685 if (!NT_STATUS_IS_OK(status)) {
4689 dosattrs = dos_mode(conn, src, &src_sbuf);
4690 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4691 ZERO_STRUCTP(&sbuf2);
4694 status = open_file_ntcreate(conn,dest,&sbuf2,
4696 FILE_SHARE_READ|FILE_SHARE_WRITE,
4697 new_create_disposition,
4703 if (!NT_STATUS_IS_OK(status)) {
4704 close_file(fsp1,ERROR_CLOSE);
4708 if ((ofun&3) == 1) {
4709 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4710 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4712 * Stop the copy from occurring.
4715 src_sbuf.st_size = 0;
4719 if (src_sbuf.st_size) {
4720 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4723 close_file(fsp1,NORMAL_CLOSE);
4725 /* Ensure the modtime is set correctly on the destination file. */
4726 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4729 * As we are opening fsp1 read-only we only expect
4730 * an error on close on fsp2 if we are out of space.
4731 * Thus we don't look at the error return from the
4734 status = close_file(fsp2,NORMAL_CLOSE);
4736 if (!NT_STATUS_IS_OK(status)) {
4740 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4741 return NT_STATUS_DISK_FULL;
4744 return NT_STATUS_OK;
4747 /****************************************************************************
4748 Reply to a file copy.
4749 ****************************************************************************/
4751 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4756 pstring mask,newname;
4759 int error = ERRnoaccess;
4761 int tid2 = SVAL(inbuf,smb_vwv0);
4762 int ofun = SVAL(inbuf,smb_vwv1);
4763 int flags = SVAL(inbuf,smb_vwv2);
4764 BOOL target_is_directory=False;
4765 BOOL source_has_wild = False;
4766 BOOL dest_has_wild = False;
4767 SMB_STRUCT_STAT sbuf1, sbuf2;
4769 START_PROFILE(SMBcopy);
4771 *directory = *mask = 0;
4774 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
4775 if (!NT_STATUS_IS_OK(status)) {
4776 END_PROFILE(SMBcopy);
4777 return ERROR_NT(status);
4779 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
4780 if (!NT_STATUS_IS_OK(status)) {
4781 END_PROFILE(SMBcopy);
4782 return ERROR_NT(status);
4785 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4787 if (tid2 != conn->cnum) {
4788 /* can't currently handle inter share copies XXXX */
4789 DEBUG(3,("Rejecting inter-share copy\n"));
4790 END_PROFILE(SMBcopy);
4791 return ERROR_DOS(ERRSRV,ERRinvdevice);
4794 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4795 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4797 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
4798 if (!NT_STATUS_IS_OK(status)) {
4799 END_PROFILE(SMBcopy);
4800 return ERROR_NT(status);
4803 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
4804 if (!NT_STATUS_IS_OK(status)) {
4805 END_PROFILE(SMBcopy);
4806 return ERROR_NT(status);
4809 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4811 if ((flags&1) && target_is_directory) {
4812 END_PROFILE(SMBcopy);
4813 return ERROR_DOS(ERRDOS,ERRbadfile);
4816 if ((flags&2) && !target_is_directory) {
4817 END_PROFILE(SMBcopy);
4818 return ERROR_DOS(ERRDOS,ERRbadpath);
4821 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4822 /* wants a tree copy! XXXX */
4823 DEBUG(3,("Rejecting tree copy\n"));
4824 END_PROFILE(SMBcopy);
4825 return ERROR_DOS(ERRSRV,ERRerror);
4828 p = strrchr_m(name,'/');
4830 pstrcpy(directory,"./");
4834 pstrcpy(directory,name);
4839 * We should only check the mangled cache
4840 * here if unix_convert failed. This means
4841 * that the path in 'mask' doesn't exist
4842 * on the file system and so we need to look
4843 * for a possible mangle. This patch from
4844 * Tine Smukavec <valentin.smukavec@hermes.si>.
4847 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4848 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4851 if (!source_has_wild) {
4852 pstrcat(directory,"/");
4853 pstrcat(directory,mask);
4854 if (dest_has_wild) {
4855 if (!resolve_wildcards(directory,newname)) {
4856 END_PROFILE(SMBcopy);
4857 return ERROR_NT(NT_STATUS_NO_MEMORY);
4861 status = check_name(conn, directory);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 return ERROR_NT(status);
4866 status = check_name(conn, newname);
4867 if (!NT_STATUS_IS_OK(status)) {
4868 return ERROR_NT(status);
4871 status = copy_file(conn,directory,newname,ofun,
4872 count,target_is_directory);
4874 if(!NT_STATUS_IS_OK(status)) {
4875 END_PROFILE(SMBcopy);
4876 return ERROR_NT(status);
4881 struct smb_Dir *dir_hnd = NULL;
4886 if (strequal(mask,"????????.???"))
4889 status = check_name(conn, directory);
4890 if (!NT_STATUS_IS_OK(status)) {
4891 return ERROR_NT(status);
4894 dir_hnd = OpenDir(conn, directory, mask, 0);
4895 if (dir_hnd == NULL) {
4896 status = map_nt_error_from_unix(errno);
4897 return ERROR_NT(status);
4902 while ((dname = ReadDirName(dir_hnd, &offset))) {
4904 pstrcpy(fname,dname);
4906 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4910 if(!mask_match(fname, mask, conn->case_sensitive)) {
4914 error = ERRnoaccess;
4915 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4916 pstrcpy(destname,newname);
4917 if (!resolve_wildcards(fname,destname)) {
4921 status = check_name(conn, fname);
4922 if (!NT_STATUS_IS_OK(status)) {
4923 return ERROR_NT(status);
4926 status = check_name(conn, destname);
4927 if (!NT_STATUS_IS_OK(status)) {
4928 return ERROR_NT(status);
4931 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
4933 status = copy_file(conn,fname,destname,ofun,
4934 count,target_is_directory);
4935 if (NT_STATUS_IS_OK(status)) {
4944 /* Error on close... */
4946 END_PROFILE(SMBcopy);
4947 return(UNIXERROR(ERRHRD,ERRgeneral));
4950 END_PROFILE(SMBcopy);
4951 return ERROR_DOS(ERRDOS,error);
4954 outsize = set_message(outbuf,1,0,True);
4955 SSVAL(outbuf,smb_vwv0,count);
4957 END_PROFILE(SMBcopy);
4961 /****************************************************************************
4963 ****************************************************************************/
4965 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4972 START_PROFILE(pathworks_setdir);
4975 if (!CAN_SETDIR(snum)) {
4976 END_PROFILE(pathworks_setdir);
4977 return ERROR_DOS(ERRDOS,ERRnoaccess);
4980 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4981 if (!NT_STATUS_IS_OK(status)) {
4982 END_PROFILE(pathworks_setdir);
4983 return ERROR_NT(status);
4986 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4988 if (strlen(newdir) != 0) {
4989 if (!vfs_directory_exist(conn,newdir,NULL)) {
4990 END_PROFILE(pathworks_setdir);
4991 return ERROR_DOS(ERRDOS,ERRbadpath);
4993 set_conn_connectpath(conn,newdir);
4996 outsize = set_message(outbuf,0,0,False);
4997 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4999 DEBUG(3,("setdir %s\n", newdir));
5001 END_PROFILE(pathworks_setdir);
5006 #define DBGC_CLASS DBGC_LOCKING
5008 /****************************************************************************
5009 Get a lock pid, dealing with large count requests.
5010 ****************************************************************************/
5012 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5014 if(!large_file_format)
5015 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5017 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5020 /****************************************************************************
5021 Get a lock count, dealing with large count requests.
5022 ****************************************************************************/
5024 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5026 SMB_BIG_UINT count = 0;
5028 if(!large_file_format) {
5029 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5032 #if defined(HAVE_LONGLONG)
5033 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5034 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5035 #else /* HAVE_LONGLONG */
5038 * NT4.x seems to be broken in that it sends large file (64 bit)
5039 * lockingX calls even if the CAP_LARGE_FILES was *not*
5040 * negotiated. For boxes without large unsigned ints truncate the
5041 * lock count by dropping the top 32 bits.
5044 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5045 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5046 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5047 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5048 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5051 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5052 #endif /* HAVE_LONGLONG */
5058 #if !defined(HAVE_LONGLONG)
5059 /****************************************************************************
5060 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5061 ****************************************************************************/
5063 static uint32 map_lock_offset(uint32 high, uint32 low)
5067 uint32 highcopy = high;
5070 * Try and find out how many significant bits there are in high.
5073 for(i = 0; highcopy; i++)
5077 * We use 31 bits not 32 here as POSIX
5078 * lock offsets may not be negative.
5081 mask = (~0) << (31 - i);
5084 return 0; /* Fail. */
5090 #endif /* !defined(HAVE_LONGLONG) */
5092 /****************************************************************************
5093 Get a lock offset, dealing with large offset requests.
5094 ****************************************************************************/
5096 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5098 SMB_BIG_UINT offset = 0;
5102 if(!large_file_format) {
5103 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5106 #if defined(HAVE_LONGLONG)
5107 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5108 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5109 #else /* HAVE_LONGLONG */
5112 * NT4.x seems to be broken in that it sends large file (64 bit)
5113 * lockingX calls even if the CAP_LARGE_FILES was *not*
5114 * negotiated. For boxes without large unsigned ints mangle the
5115 * lock offset by mapping the top 32 bits onto the lower 32.
5118 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5119 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5120 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5123 if((new_low = map_lock_offset(high, low)) == 0) {
5125 return (SMB_BIG_UINT)-1;
5128 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5129 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5130 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5131 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5134 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5135 #endif /* HAVE_LONGLONG */
5141 /****************************************************************************
5142 Reply to a lockingX request.
5143 ****************************************************************************/
5145 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5146 int length, int bufsize)
5148 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5149 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5150 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5151 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5152 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5153 SMB_BIG_UINT count = 0, offset = 0;
5155 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5158 BOOL large_file_format =
5159 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5161 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5163 START_PROFILE(SMBlockingX);
5165 CHECK_FSP(fsp,conn);
5167 data = smb_buf(inbuf);
5169 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5170 /* we don't support these - and CANCEL_LOCK makes w2k
5171 and XP reboot so I don't really want to be
5172 compatible! (tridge) */
5173 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5176 /* Check if this is an oplock break on a file
5177 we have granted an oplock on.
5179 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5180 /* Client can insist on breaking to none. */
5181 BOOL break_to_none = (oplocklevel == 0);
5184 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5185 "for fnum = %d\n", (unsigned int)oplocklevel,
5189 * Make sure we have granted an exclusive or batch oplock on
5193 if (fsp->oplock_type == 0) {
5195 /* The Samba4 nbench simulator doesn't understand
5196 the difference between break to level2 and break
5197 to none from level2 - it sends oplock break
5198 replies in both cases. Don't keep logging an error
5199 message here - just ignore it. JRA. */
5201 DEBUG(5,("reply_lockingX: Error : oplock break from "
5202 "client for fnum = %d (oplock=%d) and no "
5203 "oplock granted on this file (%s).\n",
5204 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5206 /* if this is a pure oplock break request then don't
5208 if (num_locks == 0 && num_ulocks == 0) {
5209 END_PROFILE(SMBlockingX);
5212 END_PROFILE(SMBlockingX);
5213 return ERROR_DOS(ERRDOS,ERRlock);
5217 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5219 result = remove_oplock(fsp);
5221 result = downgrade_oplock(fsp);
5225 DEBUG(0, ("reply_lockingX: error in removing "
5226 "oplock on file %s\n", fsp->fsp_name));
5227 /* Hmmm. Is this panic justified? */
5228 smb_panic("internal tdb error");
5231 reply_to_oplock_break_requests(fsp);
5233 /* if this is a pure oplock break request then don't send a
5235 if (num_locks == 0 && num_ulocks == 0) {
5236 /* Sanity check - ensure a pure oplock break is not a
5238 if(CVAL(inbuf,smb_vwv0) != 0xff)
5239 DEBUG(0,("reply_lockingX: Error : pure oplock "
5240 "break is a chained %d request !\n",
5241 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5242 END_PROFILE(SMBlockingX);
5248 * We do this check *after* we have checked this is not a oplock break
5249 * response message. JRA.
5252 release_level_2_oplocks_on_change(fsp);
5254 /* Data now points at the beginning of the list
5255 of smb_unlkrng structs */
5256 for(i = 0; i < (int)num_ulocks; i++) {
5257 lock_pid = get_lock_pid( data, i, large_file_format);
5258 count = get_lock_count( data, i, large_file_format);
5259 offset = get_lock_offset( data, i, large_file_format, &err);
5262 * There is no error code marked "stupid client bug".... :-).
5265 END_PROFILE(SMBlockingX);
5266 return ERROR_DOS(ERRDOS,ERRnoaccess);
5269 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5270 "pid %u, file %s\n", (double)offset, (double)count,
5271 (unsigned int)lock_pid, fsp->fsp_name ));
5273 status = do_unlock(fsp,
5279 if (NT_STATUS_V(status)) {
5280 END_PROFILE(SMBlockingX);
5281 return ERROR_NT(status);
5285 /* Setup the timeout in seconds. */
5287 if (!lp_blocking_locks(SNUM(conn))) {
5291 /* Now do any requested locks */
5292 data += ((large_file_format ? 20 : 10)*num_ulocks);
5294 /* Data now points at the beginning of the list
5295 of smb_lkrng structs */
5297 for(i = 0; i < (int)num_locks; i++) {
5298 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5299 READ_LOCK:WRITE_LOCK);
5300 lock_pid = get_lock_pid( data, i, large_file_format);
5301 count = get_lock_count( data, i, large_file_format);
5302 offset = get_lock_offset( data, i, large_file_format, &err);
5305 * There is no error code marked "stupid client bug".... :-).
5308 END_PROFILE(SMBlockingX);
5309 return ERROR_DOS(ERRDOS,ERRnoaccess);
5312 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5313 "%u, file %s timeout = %d\n", (double)offset,
5314 (double)count, (unsigned int)lock_pid,
5315 fsp->fsp_name, (int)lock_timeout ));
5317 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5318 if (lp_blocking_locks(SNUM(conn))) {
5320 /* Schedule a message to ourselves to
5321 remove the blocking lock record and
5322 return the right error. */
5324 if (!blocking_lock_cancel(fsp,
5330 NT_STATUS_FILE_LOCK_CONFLICT)) {
5331 END_PROFILE(SMBlockingX);
5332 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5335 /* Remove a matching pending lock. */
5336 status = do_lock_cancel(fsp,
5342 BOOL blocking_lock = lock_timeout ? True : False;
5343 BOOL defer_lock = False;
5344 struct byte_range_lock *br_lck;
5346 br_lck = do_lock(fsp,
5355 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5356 /* Windows internal resolution for blocking locks seems
5357 to be about 200ms... Don't wait for less than that. JRA. */
5358 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5359 lock_timeout = lp_lock_spin_time();
5364 /* This heuristic seems to match W2K3 very well. If a
5365 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5366 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5367 far as I can tell. Replacement for do_lock_spin(). JRA. */
5369 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5370 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5372 lock_timeout = lp_lock_spin_time();
5375 if (br_lck && defer_lock) {
5377 * A blocking lock was requested. Package up
5378 * this smb into a queued request and push it
5379 * onto the blocking lock queue.
5381 if(push_blocking_lock_request(br_lck,
5391 TALLOC_FREE(br_lck);
5392 END_PROFILE(SMBlockingX);
5397 TALLOC_FREE(br_lck);
5400 if (NT_STATUS_V(status)) {
5401 END_PROFILE(SMBlockingX);
5402 return ERROR_NT(status);
5406 /* If any of the above locks failed, then we must unlock
5407 all of the previous locks (X/Open spec). */
5409 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5413 * Ensure we don't do a remove on the lock that just failed,
5414 * as under POSIX rules, if we have a lock already there, we
5415 * will delete it (and we shouldn't) .....
5417 for(i--; i >= 0; i--) {
5418 lock_pid = get_lock_pid( data, i, large_file_format);
5419 count = get_lock_count( data, i, large_file_format);
5420 offset = get_lock_offset( data, i, large_file_format,
5424 * There is no error code marked "stupid client
5428 END_PROFILE(SMBlockingX);
5429 return ERROR_DOS(ERRDOS,ERRnoaccess);
5438 END_PROFILE(SMBlockingX);
5439 return ERROR_NT(status);
5442 set_message(outbuf,2,0,True);
5444 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5445 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5447 END_PROFILE(SMBlockingX);
5448 return chain_reply(inbuf,outbuf,length,bufsize);
5452 #define DBGC_CLASS DBGC_ALL
5454 /****************************************************************************
5455 Reply to a SMBreadbmpx (read block multiplex) request.
5456 ****************************************************************************/
5458 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5469 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5470 START_PROFILE(SMBreadBmpx);
5472 /* this function doesn't seem to work - disable by default */
5473 if (!lp_readbmpx()) {
5474 END_PROFILE(SMBreadBmpx);
5475 return ERROR_DOS(ERRSRV,ERRuseSTD);
5478 outsize = set_message(outbuf,8,0,True);
5480 CHECK_FSP(fsp,conn);
5481 if (!CHECK_READ(fsp,inbuf)) {
5482 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5485 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5486 maxcount = SVAL(inbuf,smb_vwv3);
5488 data = smb_buf(outbuf);
5489 pad = ((long)data)%4;
5494 max_per_packet = bufsize-(outsize+pad);
5498 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5499 END_PROFILE(SMBreadBmpx);
5500 return ERROR_DOS(ERRDOS,ERRlock);
5504 size_t N = MIN(max_per_packet,tcount-total_read);
5506 nread = read_file(fsp,data,startpos,N);
5511 if (nread < (ssize_t)N)
5512 tcount = total_read + nread;
5514 set_message(outbuf,8,nread+pad,False);
5515 SIVAL(outbuf,smb_vwv0,startpos);
5516 SSVAL(outbuf,smb_vwv2,tcount);
5517 SSVAL(outbuf,smb_vwv6,nread);
5518 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5521 if (!send_smb(smbd_server_fd(),outbuf))
5522 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5524 total_read += nread;
5526 } while (total_read < (ssize_t)tcount);
5528 END_PROFILE(SMBreadBmpx);
5532 /****************************************************************************
5533 Reply to a SMBsetattrE.
5534 ****************************************************************************/
5536 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5538 struct timespec ts[2];
5540 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5541 START_PROFILE(SMBsetattrE);
5543 outsize = set_message(outbuf,0,0,False);
5545 if(!fsp || (fsp->conn != conn)) {
5546 END_PROFILE(SMBsetattrE);
5547 return ERROR_DOS(ERRDOS,ERRbadfid);
5551 * Convert the DOS times into unix times. Ignore create
5552 * time as UNIX can't set this.
5555 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5556 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5559 * Patch from Ray Frush <frush@engr.colostate.edu>
5560 * Sometimes times are sent as zero - ignore them.
5563 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5564 /* Ignore request */
5565 if( DEBUGLVL( 3 ) ) {
5566 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5567 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5569 END_PROFILE(SMBsetattrE);
5571 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5572 /* set modify time = to access time if modify time was unset */
5576 /* Set the date on this file */
5577 /* Should we set pending modtime here ? JRA */
5578 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5579 END_PROFILE(SMBsetattrE);
5580 return ERROR_DOS(ERRDOS,ERRnoaccess);
5583 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5585 (unsigned int)ts[0].tv_sec,
5586 (unsigned int)ts[1].tv_sec));
5588 END_PROFILE(SMBsetattrE);
5593 /* Back from the dead for OS/2..... JRA. */
5595 /****************************************************************************
5596 Reply to a SMBwritebmpx (write block multiplex primary) request.
5597 ****************************************************************************/
5599 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5602 ssize_t nwritten = -1;
5609 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5610 START_PROFILE(SMBwriteBmpx);
5612 CHECK_FSP(fsp,conn);
5613 if (!CHECK_WRITE(fsp)) {
5614 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5616 if (HAS_CACHED_ERROR(fsp)) {
5617 return(CACHED_ERROR(fsp));
5620 tcount = SVAL(inbuf,smb_vwv1);
5621 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5622 write_through = BITSETW(inbuf+smb_vwv7,0);
5623 numtowrite = SVAL(inbuf,smb_vwv10);
5624 smb_doff = SVAL(inbuf,smb_vwv11);
5626 data = smb_base(inbuf) + smb_doff;
5628 /* If this fails we need to send an SMBwriteC response,
5629 not an SMBwritebmpx - set this up now so we don't forget */
5630 SCVAL(outbuf,smb_com,SMBwritec);
5632 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5633 END_PROFILE(SMBwriteBmpx);
5634 return(ERROR_DOS(ERRDOS,ERRlock));
5637 nwritten = write_file(fsp,data,startpos,numtowrite);
5639 sync_file(conn, fsp, write_through);
5641 if(nwritten < (ssize_t)numtowrite) {
5642 END_PROFILE(SMBwriteBmpx);
5643 return(UNIXERROR(ERRHRD,ERRdiskfull));
5646 /* If the maximum to be written to this file
5647 is greater than what we just wrote then set
5648 up a secondary struct to be attached to this
5649 fd, we will use this to cache error messages etc. */
5651 if((ssize_t)tcount > nwritten) {
5652 write_bmpx_struct *wbms;
5653 if(fsp->wbmpx_ptr != NULL)
5654 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5656 wbms = SMB_MALLOC_P(write_bmpx_struct);
5658 DEBUG(0,("Out of memory in reply_readmpx\n"));
5659 END_PROFILE(SMBwriteBmpx);
5660 return(ERROR_DOS(ERRSRV,ERRnoresource));
5662 wbms->wr_mode = write_through;
5663 wbms->wr_discard = False; /* No errors yet */
5664 wbms->wr_total_written = nwritten;
5665 wbms->wr_errclass = 0;
5667 fsp->wbmpx_ptr = wbms;
5670 /* We are returning successfully, set the message type back to
5672 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5674 outsize = set_message(outbuf,1,0,True);
5676 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5678 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5679 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5681 if (write_through && tcount==nwritten) {
5682 /* We need to send both a primary and a secondary response */
5683 smb_setlen(outbuf,outsize - 4);
5685 if (!send_smb(smbd_server_fd(),outbuf))
5686 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5688 /* Now the secondary */
5689 outsize = set_message(outbuf,1,0,True);
5690 SCVAL(outbuf,smb_com,SMBwritec);
5691 SSVAL(outbuf,smb_vwv0,nwritten);
5694 END_PROFILE(SMBwriteBmpx);
5698 /****************************************************************************
5699 Reply to a SMBwritebs (write block multiplex secondary) request.
5700 ****************************************************************************/
5702 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5705 ssize_t nwritten = -1;
5712 write_bmpx_struct *wbms;
5713 BOOL send_response = False;
5714 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5715 START_PROFILE(SMBwriteBs);
5717 CHECK_FSP(fsp,conn);
5718 if (!CHECK_WRITE(fsp)) {
5719 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5722 tcount = SVAL(inbuf,smb_vwv1);
5723 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5724 numtowrite = SVAL(inbuf,smb_vwv6);
5725 smb_doff = SVAL(inbuf,smb_vwv7);
5727 data = smb_base(inbuf) + smb_doff;
5729 /* We need to send an SMBwriteC response, not an SMBwritebs */
5730 SCVAL(outbuf,smb_com,SMBwritec);
5732 /* This fd should have an auxiliary struct attached,
5733 check that it does */
5734 wbms = fsp->wbmpx_ptr;
5736 END_PROFILE(SMBwriteBs);
5740 /* If write through is set we can return errors, else we must cache them */
5741 write_through = wbms->wr_mode;
5743 /* Check for an earlier error */
5744 if(wbms->wr_discard) {
5745 END_PROFILE(SMBwriteBs);
5746 return -1; /* Just discard the packet */
5749 nwritten = write_file(fsp,data,startpos,numtowrite);
5751 sync_file(conn, fsp, write_through);
5753 if (nwritten < (ssize_t)numtowrite) {
5755 /* We are returning an error - we can delete the aux struct */
5758 fsp->wbmpx_ptr = NULL;
5759 END_PROFILE(SMBwriteBs);
5760 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5762 wbms->wr_errclass = ERRHRD;
5763 wbms->wr_error = ERRdiskfull;
5764 wbms->wr_status = NT_STATUS_DISK_FULL;
5765 wbms->wr_discard = True;
5766 END_PROFILE(SMBwriteBs);
5770 /* Increment the total written, if this matches tcount
5771 we can discard the auxiliary struct (hurrah !) and return a writeC */
5772 wbms->wr_total_written += nwritten;
5773 if(wbms->wr_total_written >= tcount) {
5774 if (write_through) {
5775 outsize = set_message(outbuf,1,0,True);
5776 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5777 send_response = True;
5781 fsp->wbmpx_ptr = NULL;
5785 END_PROFILE(SMBwriteBs);
5789 END_PROFILE(SMBwriteBs);
5793 /****************************************************************************
5794 Reply to a SMBgetattrE.
5795 ****************************************************************************/
5797 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5799 SMB_STRUCT_STAT sbuf;
5802 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5803 START_PROFILE(SMBgetattrE);
5805 outsize = set_message(outbuf,11,0,True);
5807 if(!fsp || (fsp->conn != conn)) {
5808 END_PROFILE(SMBgetattrE);
5809 return ERROR_DOS(ERRDOS,ERRbadfid);
5812 /* Do an fstat on this file */
5813 if(fsp_stat(fsp, &sbuf)) {
5814 END_PROFILE(SMBgetattrE);
5815 return(UNIXERROR(ERRDOS,ERRnoaccess));
5818 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5821 * Convert the times into dos times. Set create
5822 * date to be last modify date as UNIX doesn't save
5826 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5827 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5828 /* Should we check pending modtime here ? JRA */
5829 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5832 SIVAL(outbuf,smb_vwv6,0);
5833 SIVAL(outbuf,smb_vwv8,0);
5835 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5836 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5837 SIVAL(outbuf,smb_vwv8,allocation_size);
5839 SSVAL(outbuf,smb_vwv10, mode);
5841 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5843 END_PROFILE(SMBgetattrE);