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 /* Custom version for processing POSIX paths. */
48 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
50 NTSTATUS check_path_syntax_internal(pstring destname,
51 const pstring srcname,
53 BOOL *p_last_component_contains_wcard)
56 const char *s = srcname;
57 NTSTATUS ret = NT_STATUS_OK;
58 BOOL start_of_name_component = True;
59 BOOL stream_component = False;;
61 *p_last_component_contains_wcard = False;
64 if (IS_PATH_SEP(*s,posix_path)) {
66 * Safe to assume is not the second part of a mb char as this is handled below.
68 /* Eat multiple '/' or '\\' */
69 while (IS_PATH_SEP(*s,posix_path)) {
72 if ((d != destname) && (*s != '\0')) {
73 /* We only care about non-leading or trailing '/' or '\\' */
77 start_of_name_component = True;
79 *p_last_component_contains_wcard = False;
83 if (start_of_name_component) {
84 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
85 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
88 * No mb char starts with '.' so we're safe checking the directory separator here.
91 /* If we just added a '/' - delete it */
92 if ((d > destname) && (*(d-1) == '/')) {
97 /* Are we at the start ? Can't go back further if so. */
99 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
102 /* Go back one level... */
103 /* We know this is safe as '/' cannot be part of a mb sequence. */
104 /* NOTE - if this assumption is invalid we are not in good shape... */
105 /* Decrement d first as d points to the *next* char to write into. */
106 for (d--; d > destname; d--) {
110 s += 2; /* Else go past the .. */
111 /* We're still at the start of a name component, just the previous one. */
114 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
126 if (!stream_component && *s <= 0x1f) {
127 return NT_STATUS_OBJECT_NAME_INVALID;
131 stream_component = True;
138 *p_last_component_contains_wcard = True;
147 /* Get the size of the next MB character. */
148 next_codepoint(s,&siz);
166 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
168 return NT_STATUS_INVALID_PARAMETER;
171 start_of_name_component = False;
178 /****************************************************************************
179 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
180 No wildcards allowed.
181 ****************************************************************************/
183 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
186 return check_path_syntax_internal(destname, srcname, False, &ignore);
189 /****************************************************************************
190 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
191 Wildcards allowed - p_contains_wcard returns true if the last component contained
193 ****************************************************************************/
195 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
197 return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
200 /****************************************************************************
201 Check the path for a POSIX client.
202 We're assuming here that '/' is not the second byte in any multibyte char
203 set (a safe assumption).
204 ****************************************************************************/
206 NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
209 return check_path_syntax_internal(destname, srcname, True, &ignore);
212 /****************************************************************************
213 Pull a string and check the path allowing a wilcard - provide for error return.
214 ****************************************************************************/
216 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
217 NTSTATUS *err, BOOL *contains_wcard)
220 char *tmppath_ptr = tmppath;
223 SMB_ASSERT(dest_len == sizeof(pstring));
227 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
229 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
232 *contains_wcard = False;
234 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
236 * For a DFS path the function parse_dfs_path()
237 * will do the path processing, just make a copy.
239 pstrcpy(dest, tmppath);
244 if (lp_posix_pathnames()) {
245 *err = check_path_syntax_posix(dest, tmppath);
247 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
253 /****************************************************************************
254 Pull a string and check the path - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
260 char *tmppath_ptr = tmppath;
263 SMB_ASSERT(dest_len == sizeof(pstring));
267 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
269 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
272 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
274 * For a DFS path the function parse_dfs_path()
275 * will do the path processing, just make a copy.
277 pstrcpy(dest, tmppath);
282 if (lp_posix_pathnames()) {
283 *err = check_path_syntax_posix(dest, tmppath);
285 *err = check_path_syntax(dest, tmppath);
291 /****************************************************************************
292 Reply to a special message.
293 ****************************************************************************/
295 int reply_special(char *inbuf,char *outbuf)
298 int msg_type = CVAL(inbuf,0);
299 int msg_flags = CVAL(inbuf,1);
303 static BOOL already_got_session = False;
307 memset(outbuf,'\0',smb_size);
309 smb_setlen(outbuf,0);
312 case 0x81: /* session request */
314 if (already_got_session) {
315 exit_server_cleanly("multiple session request not permitted");
318 SCVAL(outbuf,0,0x82);
320 if (name_len(inbuf+4) > 50 ||
321 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
322 DEBUG(0,("Invalid name length in session request\n"));
325 name_extract(inbuf,4,name1);
326 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
327 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
330 set_local_machine_name(name1, True);
331 set_remote_machine_name(name2, True);
333 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
334 get_local_machine_name(), get_remote_machine_name(),
337 if (name_type == 'R') {
338 /* We are being asked for a pathworks session ---
340 SCVAL(outbuf, 0,0x83);
344 /* only add the client's machine name to the list
345 of possibly valid usernames if we are operating
346 in share mode security */
347 if (lp_security() == SEC_SHARE) {
348 add_session_user(get_remote_machine_name());
351 reload_services(True);
354 already_got_session = True;
357 case 0x89: /* session keepalive request
358 (some old clients produce this?) */
359 SCVAL(outbuf,0,SMBkeepalive);
363 case 0x82: /* positive session response */
364 case 0x83: /* negative session response */
365 case 0x84: /* retarget session response */
366 DEBUG(0,("Unexpected session response\n"));
369 case SMBkeepalive: /* session keepalive */
374 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
375 msg_type, msg_flags));
380 /****************************************************************************
382 conn POINTER CAN BE NULL HERE !
383 ****************************************************************************/
385 int reply_tcon(connection_struct *conn,
386 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
393 uint16 vuid = SVAL(inbuf,smb_uid);
397 DATA_BLOB password_blob;
399 START_PROFILE(SMBtcon);
401 *service_buf = *password = *dev = 0;
403 p = smb_buf(inbuf)+1;
404 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
405 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
407 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
409 p = strrchr_m(service_buf,'\\');
413 service = service_buf;
416 password_blob = data_blob(password, pwlen+1);
418 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
420 data_blob_clear_free(&password_blob);
423 END_PROFILE(SMBtcon);
424 return ERROR_NT(nt_status);
427 outsize = set_message(outbuf,2,0,True);
428 SSVAL(outbuf,smb_vwv0,max_recv);
429 SSVAL(outbuf,smb_vwv1,conn->cnum);
430 SSVAL(outbuf,smb_tid,conn->cnum);
432 DEBUG(3,("tcon service=%s cnum=%d\n",
433 service, conn->cnum));
435 END_PROFILE(SMBtcon);
439 /****************************************************************************
440 Reply to a tcon and X.
441 conn POINTER CAN BE NULL HERE !
442 ****************************************************************************/
444 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
449 /* what the cleint thinks the device is */
450 fstring client_devicetype;
451 /* what the server tells the client the share represents */
452 const char *server_devicetype;
454 uint16 vuid = SVAL(inbuf,smb_uid);
455 int passlen = SVAL(inbuf,smb_vwv3);
458 uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
460 START_PROFILE(SMBtconX);
462 *service = *client_devicetype = 0;
464 /* we might have to close an old one */
465 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
466 close_cnum(conn,vuid);
469 if (passlen > MAX_PASS_LEN) {
470 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
473 if (global_encrypted_passwords_negotiated) {
474 password = data_blob(smb_buf(inbuf),passlen);
475 if (lp_security() == SEC_SHARE) {
477 * Security = share always has a pad byte
478 * after the password.
480 p = smb_buf(inbuf) + passlen + 1;
482 p = smb_buf(inbuf) + passlen;
485 password = data_blob(smb_buf(inbuf),passlen+1);
486 /* Ensure correct termination */
487 password.data[passlen]=0;
488 p = smb_buf(inbuf) + passlen + 1;
491 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
494 * the service name can be either: \\server\share
495 * or share directly like on the DELL PowerVault 705
498 q = strchr_m(path+2,'\\');
500 END_PROFILE(SMBtconX);
501 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
503 fstrcpy(service,q+1);
506 fstrcpy(service,path);
508 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
510 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
512 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
514 data_blob_clear_free(&password);
517 END_PROFILE(SMBtconX);
518 return ERROR_NT(nt_status);
522 server_devicetype = "IPC";
523 else if ( IS_PRINT(conn) )
524 server_devicetype = "LPT1:";
526 server_devicetype = "A:";
528 if (Protocol < PROTOCOL_NT1) {
529 set_message(outbuf,2,0,True);
531 p += srvstr_push(outbuf, p, server_devicetype, -1,
532 STR_TERMINATE|STR_ASCII);
533 set_message_end(outbuf,p);
535 /* NT sets the fstype of IPC$ to the null string */
536 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
538 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
539 /* Return permissions. */
543 set_message(outbuf,7,0,True);
546 perm1 = FILE_ALL_ACCESS;
547 perm2 = FILE_ALL_ACCESS;
549 perm1 = CAN_WRITE(conn) ?
554 SIVAL(outbuf, smb_vwv3, perm1);
555 SIVAL(outbuf, smb_vwv5, perm2);
557 set_message(outbuf,3,0,True);
561 p += srvstr_push(outbuf, p, server_devicetype, -1,
562 STR_TERMINATE|STR_ASCII);
563 p += srvstr_push(outbuf, p, fstype, -1,
566 set_message_end(outbuf,p);
568 /* what does setting this bit do? It is set by NT4 and
569 may affect the ability to autorun mounted cdroms */
570 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
571 (lp_csc_policy(SNUM(conn)) << 2));
573 init_dfsroot(conn, inbuf, outbuf);
577 DEBUG(3,("tconX service=%s \n",
580 /* set the incoming and outgoing tid to the just created one */
581 SSVAL(inbuf,smb_tid,conn->cnum);
582 SSVAL(outbuf,smb_tid,conn->cnum);
584 END_PROFILE(SMBtconX);
585 return chain_reply(inbuf,outbuf,length,bufsize);
588 /****************************************************************************
589 Reply to an unknown type.
590 ****************************************************************************/
592 int reply_unknown(char *inbuf,char *outbuf)
595 type = CVAL(inbuf,smb_com);
597 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
598 smb_fn_name(type), type, type));
600 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
603 /****************************************************************************
605 conn POINTER CAN BE NULL HERE !
606 ****************************************************************************/
608 int reply_ioctl(connection_struct *conn,
609 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
611 uint16 device = SVAL(inbuf,smb_vwv1);
612 uint16 function = SVAL(inbuf,smb_vwv2);
613 uint32 ioctl_code = (device << 16) + function;
614 int replysize, outsize;
616 START_PROFILE(SMBioctl);
618 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
620 switch (ioctl_code) {
621 case IOCTL_QUERY_JOB_INFO:
625 END_PROFILE(SMBioctl);
626 return(ERROR_DOS(ERRSRV,ERRnosupport));
629 outsize = set_message(outbuf,8,replysize+1,True);
630 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
631 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
632 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
633 p = smb_buf(outbuf) + 1; /* Allow for alignment */
635 switch (ioctl_code) {
636 case IOCTL_QUERY_JOB_INFO:
638 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
640 END_PROFILE(SMBioctl);
641 return(UNIXERROR(ERRDOS,ERRbadfid));
643 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
644 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
646 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
652 END_PROFILE(SMBioctl);
656 /****************************************************************************
657 Strange checkpath NTSTATUS mapping.
658 ****************************************************************************/
660 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
662 /* Strange DOS error code semantics only for checkpath... */
663 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
664 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
665 /* We need to map to ERRbadpath */
666 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
672 /****************************************************************************
673 Reply to a checkpath.
674 ****************************************************************************/
676 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
680 SMB_STRUCT_STAT sbuf;
683 START_PROFILE(SMBcheckpath);
685 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
686 if (!NT_STATUS_IS_OK(status)) {
687 END_PROFILE(SMBcheckpath);
688 status = map_checkpath_error(inbuf, status);
689 return ERROR_NT(status);
692 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
693 if (!NT_STATUS_IS_OK(status)) {
694 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
695 END_PROFILE(SMBcheckpath);
696 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
701 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
703 status = unix_convert(conn, name, False, NULL, &sbuf);
704 if (!NT_STATUS_IS_OK(status)) {
708 status = check_name(conn, name);
709 if (!NT_STATUS_IS_OK(status)) {
710 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
714 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
715 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
716 status = map_nt_error_from_unix(errno);
720 if (!S_ISDIR(sbuf.st_mode)) {
721 END_PROFILE(SMBcheckpath);
722 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
725 outsize = set_message(outbuf,0,0,False);
727 END_PROFILE(SMBcheckpath);
732 END_PROFILE(SMBcheckpath);
734 /* We special case this - as when a Windows machine
735 is parsing a path is steps through the components
736 one at a time - if a component fails it expects
737 ERRbadpath, not ERRbadfile.
739 status = map_checkpath_error(inbuf, status);
740 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
742 * Windows returns different error codes if
743 * the parent directory is valid but not the
744 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
745 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
746 * if the path is invalid.
748 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
751 return ERROR_NT(status);
754 /****************************************************************************
756 ****************************************************************************/
758 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
762 SMB_STRUCT_STAT sbuf;
769 START_PROFILE(SMBgetatr);
771 p = smb_buf(inbuf) + 1;
772 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
773 if (!NT_STATUS_IS_OK(status)) {
774 END_PROFILE(SMBgetatr);
775 return ERROR_NT(status);
778 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
779 if (!NT_STATUS_IS_OK(status)) {
780 END_PROFILE(SMBgetatr);
781 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
782 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
784 return ERROR_NT(status);
787 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
788 under WfWg - weird! */
789 if (*fname == '\0') {
790 mode = aHIDDEN | aDIR;
791 if (!CAN_WRITE(conn)) {
797 status = unix_convert(conn, fname, False, NULL,&sbuf);
798 if (!NT_STATUS_IS_OK(status)) {
799 END_PROFILE(SMBgetatr);
800 return ERROR_NT(status);
802 status = check_name(conn, fname);
803 if (!NT_STATUS_IS_OK(status)) {
804 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
805 END_PROFILE(SMBgetatr);
806 return ERROR_NT(status);
808 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
809 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
810 return UNIXERROR(ERRDOS,ERRbadfile);
813 mode = dos_mode(conn,fname,&sbuf);
815 mtime = sbuf.st_mtime;
821 outsize = set_message(outbuf,10,0,True);
823 SSVAL(outbuf,smb_vwv0,mode);
824 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
825 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
827 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
829 SIVAL(outbuf,smb_vwv3,(uint32)size);
831 if (Protocol >= PROTOCOL_NT1) {
832 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
835 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
837 END_PROFILE(SMBgetatr);
841 /****************************************************************************
843 ****************************************************************************/
845 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
851 SMB_STRUCT_STAT sbuf;
855 START_PROFILE(SMBsetatr);
857 p = smb_buf(inbuf) + 1;
858 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
859 if (!NT_STATUS_IS_OK(status)) {
860 END_PROFILE(SMBsetatr);
861 return ERROR_NT(status);
864 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
865 if (!NT_STATUS_IS_OK(status)) {
866 END_PROFILE(SMBsetatr);
867 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
868 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
870 return ERROR_NT(status);
873 status = unix_convert(conn, fname, False, NULL, &sbuf);
874 if (!NT_STATUS_IS_OK(status)) {
875 END_PROFILE(SMBsetatr);
876 return ERROR_NT(status);
879 status = check_name(conn, fname);
880 if (!NT_STATUS_IS_OK(status)) {
881 END_PROFILE(SMBsetatr);
882 return ERROR_NT(status);
885 if (fname[0] == '.' && fname[1] == '\0') {
887 * Not sure here is the right place to catch this
888 * condition. Might be moved to somewhere else later -- vl
890 END_PROFILE(SMBsetatr);
891 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
894 mode = SVAL(inbuf,smb_vwv0);
895 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
897 if (mode != FILE_ATTRIBUTE_NORMAL) {
898 if (VALID_STAT_OF_DIR(sbuf))
903 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
904 END_PROFILE(SMBsetatr);
905 return UNIXERROR(ERRDOS, ERRnoaccess);
909 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
910 END_PROFILE(SMBsetatr);
911 return UNIXERROR(ERRDOS, ERRnoaccess);
914 outsize = set_message(outbuf,0,0,False);
916 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
918 END_PROFILE(SMBsetatr);
922 /****************************************************************************
924 ****************************************************************************/
926 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
929 SMB_BIG_UINT dfree,dsize,bsize;
930 START_PROFILE(SMBdskattr);
932 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
933 END_PROFILE(SMBdskattr);
934 return(UNIXERROR(ERRHRD,ERRgeneral));
937 outsize = set_message(outbuf,5,0,True);
939 if (Protocol <= PROTOCOL_LANMAN2) {
940 double total_space, free_space;
941 /* we need to scale this to a number that DOS6 can handle. We
942 use floating point so we can handle large drives on systems
943 that don't have 64 bit integers
945 we end up displaying a maximum of 2G to DOS systems
947 total_space = dsize * (double)bsize;
948 free_space = dfree * (double)bsize;
950 dsize = (total_space+63*512) / (64*512);
951 dfree = (free_space+63*512) / (64*512);
953 if (dsize > 0xFFFF) dsize = 0xFFFF;
954 if (dfree > 0xFFFF) dfree = 0xFFFF;
956 SSVAL(outbuf,smb_vwv0,dsize);
957 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
958 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
959 SSVAL(outbuf,smb_vwv3,dfree);
961 SSVAL(outbuf,smb_vwv0,dsize);
962 SSVAL(outbuf,smb_vwv1,bsize/512);
963 SSVAL(outbuf,smb_vwv2,512);
964 SSVAL(outbuf,smb_vwv3,dfree);
967 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
969 END_PROFILE(SMBdskattr);
973 /****************************************************************************
975 Can be called from SMBsearch, SMBffirst or SMBfunique.
976 ****************************************************************************/
978 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
988 unsigned int numentries = 0;
989 unsigned int maxentries = 0;
990 BOOL finished = False;
996 BOOL check_descend = False;
997 BOOL expect_close = False;
999 BOOL mask_contains_wcard = False;
1000 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1002 START_PROFILE(SMBsearch);
1004 if (lp_posix_pathnames()) {
1005 END_PROFILE(SMBsearch);
1006 return reply_unknown(inbuf, outbuf);
1009 *mask = *directory = *fname = 0;
1011 /* If we were called as SMBffirst then we must expect close. */
1012 if(CVAL(inbuf,smb_com) == SMBffirst) {
1013 expect_close = True;
1016 outsize = set_message(outbuf,1,3,True);
1017 maxentries = SVAL(inbuf,smb_vwv0);
1018 dirtype = SVAL(inbuf,smb_vwv1);
1019 p = smb_buf(inbuf) + 1;
1020 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1021 if (!NT_STATUS_IS_OK(nt_status)) {
1022 END_PROFILE(SMBsearch);
1023 return ERROR_NT(nt_status);
1026 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1027 if (!NT_STATUS_IS_OK(nt_status)) {
1028 END_PROFILE(SMBsearch);
1029 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1030 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1032 return ERROR_NT(nt_status);
1036 status_len = SVAL(p, 0);
1039 /* dirtype &= ~aDIR; */
1041 if (status_len == 0) {
1042 SMB_STRUCT_STAT sbuf;
1044 pstrcpy(directory,path);
1045 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1046 if (!NT_STATUS_IS_OK(nt_status)) {
1047 END_PROFILE(SMBsearch);
1048 return ERROR_NT(nt_status);
1051 nt_status = check_name(conn, directory);
1052 if (!NT_STATUS_IS_OK(nt_status)) {
1053 END_PROFILE(SMBsearch);
1054 return ERROR_NT(nt_status);
1057 p = strrchr_m(directory,'/');
1059 pstrcpy(mask,directory);
1060 pstrcpy(directory,".");
1066 if (*directory == '\0') {
1067 pstrcpy(directory,".");
1069 memset((char *)status,'\0',21);
1070 SCVAL(status,0,(dirtype & 0x1F));
1074 memcpy(status,p,21);
1075 status_dirtype = CVAL(status,0) & 0x1F;
1076 if (status_dirtype != (dirtype & 0x1F)) {
1077 dirtype = status_dirtype;
1080 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1081 if (!conn->dirptr) {
1084 string_set(&conn->dirpath,dptr_path(dptr_num));
1085 pstrcpy(mask, dptr_wcard(dptr_num));
1087 * For a 'continue' search we have no string. So
1088 * check from the initial saved string.
1090 mask_contains_wcard = ms_has_wild(mask);
1093 p = smb_buf(outbuf) + 3;
1095 if (status_len == 0) {
1096 nt_status = dptr_create(conn,
1100 SVAL(inbuf,smb_pid),
1102 mask_contains_wcard,
1105 if (!NT_STATUS_IS_OK(nt_status)) {
1106 return ERROR_NT(nt_status);
1108 dptr_num = dptr_dnum(conn->dirptr);
1110 dirtype = dptr_attr(dptr_num);
1113 DEBUG(4,("dptr_num is %d\n",dptr_num));
1115 if ((dirtype&0x1F) == aVOLID) {
1116 memcpy(p,status,21);
1117 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1118 0,aVOLID,0,!allow_long_path_components);
1119 dptr_fill(p+12,dptr_num);
1120 if (dptr_zero(p+12) && (status_len==0)) {
1125 p += DIR_STRUCT_SIZE;
1128 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1130 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1131 conn->dirpath,lp_dontdescend(SNUM(conn))));
1132 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1133 check_descend = True;
1136 for (i=numentries;(i<maxentries) && !finished;i++) {
1137 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1139 memcpy(p,status,21);
1140 make_dir_struct(p,mask,fname,size, mode,date,
1141 !allow_long_path_components);
1142 if (!dptr_fill(p+12,dptr_num)) {
1146 p += DIR_STRUCT_SIZE;
1153 /* If we were called as SMBffirst with smb_search_id == NULL
1154 and no entries were found then return error and close dirptr
1157 if (numentries == 0) {
1158 dptr_close(&dptr_num);
1159 } else if(expect_close && status_len == 0) {
1160 /* Close the dptr - we know it's gone */
1161 dptr_close(&dptr_num);
1164 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1165 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1166 dptr_close(&dptr_num);
1169 if ((numentries == 0) && !mask_contains_wcard) {
1170 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1173 SSVAL(outbuf,smb_vwv0,numentries);
1174 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1175 SCVAL(smb_buf(outbuf),0,5);
1176 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1178 /* The replies here are never long name. */
1179 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1180 if (!allow_long_path_components) {
1181 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1184 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1185 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1187 outsize += DIR_STRUCT_SIZE*numentries;
1188 smb_setlen(outbuf,outsize - 4);
1190 if ((! *directory) && dptr_path(dptr_num))
1191 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1193 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1194 smb_fn_name(CVAL(inbuf,smb_com)),
1195 mask, directory, dirtype, numentries, maxentries ) );
1197 END_PROFILE(SMBsearch);
1201 /****************************************************************************
1202 Reply to a fclose (stop directory search).
1203 ****************************************************************************/
1205 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1214 BOOL path_contains_wcard = False;
1216 START_PROFILE(SMBfclose);
1218 if (lp_posix_pathnames()) {
1219 END_PROFILE(SMBfclose);
1220 return reply_unknown(inbuf, outbuf);
1223 outsize = set_message(outbuf,1,0,True);
1224 p = smb_buf(inbuf) + 1;
1225 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1226 if (!NT_STATUS_IS_OK(err)) {
1227 END_PROFILE(SMBfclose);
1228 return ERROR_NT(err);
1231 status_len = SVAL(p,0);
1234 if (status_len == 0) {
1235 END_PROFILE(SMBfclose);
1236 return ERROR_DOS(ERRSRV,ERRsrverror);
1239 memcpy(status,p,21);
1241 if(dptr_fetch(status+12,&dptr_num)) {
1242 /* Close the dptr - we know it's gone */
1243 dptr_close(&dptr_num);
1246 SSVAL(outbuf,smb_vwv0,0);
1248 DEBUG(3,("search close\n"));
1250 END_PROFILE(SMBfclose);
1254 /****************************************************************************
1256 ****************************************************************************/
1258 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1266 SMB_STRUCT_STAT sbuf;
1268 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1270 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1273 uint32 create_disposition;
1274 uint32 create_options = 0;
1276 START_PROFILE(SMBopen);
1278 deny_mode = SVAL(inbuf,smb_vwv0);
1280 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 END_PROFILE(SMBopen);
1283 return ERROR_NT(status);
1286 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 END_PROFILE(SMBopen);
1289 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1290 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1292 return ERROR_NT(status);
1295 status = unix_convert(conn, fname, False, NULL, &sbuf);
1296 if (!NT_STATUS_IS_OK(status)) {
1297 END_PROFILE(SMBopen);
1298 return ERROR_NT(status);
1301 status = check_name(conn, fname);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 END_PROFILE(SMBopen);
1304 return ERROR_NT(status);
1307 if( is_ntfs_stream_name(fname)) {
1308 END_PROFILE(SMBopen);
1309 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1312 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1313 &access_mask, &share_mode, &create_disposition, &create_options)) {
1314 END_PROFILE(SMBopen);
1315 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1318 status = open_file_ntcreate(conn,fname,&sbuf,
1327 if (!NT_STATUS_IS_OK(status)) {
1328 END_PROFILE(SMBopen);
1329 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1330 /* We have re-scheduled this call. */
1333 return ERROR_OPEN(status);
1336 size = sbuf.st_size;
1337 fattr = dos_mode(conn,fname,&sbuf);
1338 mtime = sbuf.st_mtime;
1341 DEBUG(3,("attempt to open a directory %s\n",fname));
1342 close_file(fsp,ERROR_CLOSE);
1343 END_PROFILE(SMBopen);
1344 return ERROR_DOS(ERRDOS,ERRnoaccess);
1347 outsize = set_message(outbuf,7,0,True);
1348 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1349 SSVAL(outbuf,smb_vwv1,fattr);
1350 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1351 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1353 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1355 SIVAL(outbuf,smb_vwv4,(uint32)size);
1356 SSVAL(outbuf,smb_vwv6,deny_mode);
1358 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1359 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1362 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1363 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1365 END_PROFILE(SMBopen);
1369 /****************************************************************************
1370 Reply to an open and X.
1371 ****************************************************************************/
1373 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1376 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1377 int deny_mode = SVAL(inbuf,smb_vwv3);
1378 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1379 /* Breakout the oplock request bits so we can set the
1380 reply bits separately. */
1381 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1382 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1383 int oplock_request = ex_oplock_request | core_oplock_request;
1385 int smb_sattr = SVAL(inbuf,smb_vwv4);
1386 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1388 int smb_ofun = SVAL(inbuf,smb_vwv8);
1391 SMB_STRUCT_STAT sbuf;
1395 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1396 ssize_t retval = -1;
1399 uint32 create_disposition;
1400 uint32 create_options = 0;
1402 START_PROFILE(SMBopenX);
1404 /* If it's an IPC, pass off the pipe handler. */
1406 if (lp_nt_pipe_support()) {
1407 END_PROFILE(SMBopenX);
1408 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1410 END_PROFILE(SMBopenX);
1411 return ERROR_DOS(ERRSRV,ERRaccess);
1415 /* XXXX we need to handle passed times, sattr and flags */
1416 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1417 if (!NT_STATUS_IS_OK(status)) {
1418 END_PROFILE(SMBopenX);
1419 return ERROR_NT(status);
1422 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 END_PROFILE(SMBopenX);
1425 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1426 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1428 return ERROR_NT(status);
1431 status = unix_convert(conn, fname, False, NULL, &sbuf);
1432 if (!NT_STATUS_IS_OK(status)) {
1433 END_PROFILE(SMBopenX);
1434 return ERROR_NT(status);
1437 status = check_name(conn, fname);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 END_PROFILE(SMBopenX);
1440 return ERROR_NT(status);
1443 if (is_ntfs_stream_name(fname)) {
1444 END_PROFILE(SMBopenX);
1445 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1448 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1451 &create_disposition,
1453 END_PROFILE(SMBopenX);
1454 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1457 status = open_file_ntcreate(conn,fname,&sbuf,
1466 if (!NT_STATUS_IS_OK(status)) {
1467 END_PROFILE(SMBopenX);
1468 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1469 /* We have re-scheduled this call. */
1472 return ERROR_OPEN(status);
1475 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1476 if the file is truncated or created. */
1477 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1478 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1479 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1480 close_file(fsp,ERROR_CLOSE);
1481 END_PROFILE(SMBopenX);
1482 return ERROR_NT(NT_STATUS_DISK_FULL);
1484 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1486 close_file(fsp,ERROR_CLOSE);
1487 END_PROFILE(SMBopenX);
1488 return ERROR_NT(NT_STATUS_DISK_FULL);
1490 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1493 fattr = dos_mode(conn,fname,&sbuf);
1494 mtime = sbuf.st_mtime;
1496 close_file(fsp,ERROR_CLOSE);
1497 END_PROFILE(SMBopenX);
1498 return ERROR_DOS(ERRDOS,ERRnoaccess);
1501 /* If the caller set the extended oplock request bit
1502 and we granted one (by whatever means) - set the
1503 correct bit for extended oplock reply.
1506 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1507 smb_action |= EXTENDED_OPLOCK_GRANTED;
1510 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1511 smb_action |= EXTENDED_OPLOCK_GRANTED;
1514 /* If the caller set the core oplock request bit
1515 and we granted one (by whatever means) - set the
1516 correct bit for core oplock reply.
1519 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1520 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1523 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1524 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1527 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1528 set_message(outbuf,19,0,True);
1530 set_message(outbuf,15,0,True);
1532 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1533 SSVAL(outbuf,smb_vwv3,fattr);
1534 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1535 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1537 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1539 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1540 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1541 SSVAL(outbuf,smb_vwv11,smb_action);
1543 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1544 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1547 END_PROFILE(SMBopenX);
1548 return chain_reply(inbuf,outbuf,length,bufsize);
1551 /****************************************************************************
1552 Reply to a SMBulogoffX.
1553 conn POINTER CAN BE NULL HERE !
1554 ****************************************************************************/
1556 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1558 uint16 vuid = SVAL(inbuf,smb_uid);
1559 user_struct *vuser = get_valid_user_struct(vuid);
1560 START_PROFILE(SMBulogoffX);
1563 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1565 /* in user level security we are supposed to close any files
1566 open by this user */
1567 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1568 file_close_user(vuid);
1570 invalidate_vuid(vuid);
1572 set_message(outbuf,2,0,True);
1574 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1576 END_PROFILE(SMBulogoffX);
1577 return chain_reply(inbuf,outbuf,length,bufsize);
1580 /****************************************************************************
1581 Reply to a mknew or a create.
1582 ****************************************************************************/
1584 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1589 uint32 fattr = SVAL(inbuf,smb_vwv0);
1590 struct timespec ts[2];
1592 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1593 SMB_STRUCT_STAT sbuf;
1595 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1596 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1597 uint32 create_disposition;
1598 uint32 create_options = 0;
1600 START_PROFILE(SMBcreate);
1602 com = SVAL(inbuf,smb_com);
1604 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1606 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 END_PROFILE(SMBcreate);
1609 return ERROR_NT(status);
1612 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 END_PROFILE(SMBcreate);
1615 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1616 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1618 return ERROR_NT(status);
1621 status = unix_convert(conn, fname, False, NULL, &sbuf);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 END_PROFILE(SMBcreate);
1624 return ERROR_NT(status);
1627 status = check_name(conn, fname);
1628 if (!NT_STATUS_IS_OK(status)) {
1629 END_PROFILE(SMBcreate);
1630 return ERROR_NT(status);
1633 if (fattr & aVOLID) {
1634 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1637 if(com == SMBmknew) {
1638 /* We should fail if file exists. */
1639 create_disposition = FILE_CREATE;
1641 /* Create if file doesn't exist, truncate if it does. */
1642 create_disposition = FILE_OVERWRITE_IF;
1645 /* Open file using ntcreate. */
1646 status = open_file_ntcreate(conn,fname,&sbuf,
1655 if (!NT_STATUS_IS_OK(status)) {
1656 END_PROFILE(SMBcreate);
1657 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1658 /* We have re-scheduled this call. */
1661 return ERROR_OPEN(status);
1664 ts[0] = get_atimespec(&sbuf); /* atime. */
1665 file_ntimes(conn, fname, ts);
1667 outsize = set_message(outbuf,1,0,True);
1668 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1670 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1671 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1674 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1675 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1678 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1679 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1681 END_PROFILE(SMBcreate);
1685 /****************************************************************************
1686 Reply to a create temporary file.
1687 ****************************************************************************/
1689 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1693 uint32 fattr = SVAL(inbuf,smb_vwv0);
1695 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1697 SMB_STRUCT_STAT sbuf;
1700 unsigned int namelen;
1702 START_PROFILE(SMBctemp);
1704 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 END_PROFILE(SMBctemp);
1707 return ERROR_NT(status);
1710 pstrcat(fname,"/TMXXXXXX");
1712 pstrcat(fname,"TMXXXXXX");
1715 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 END_PROFILE(SMBctemp);
1718 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1719 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1721 return ERROR_NT(status);
1724 status = unix_convert(conn, fname, False, NULL, &sbuf);
1725 if (!NT_STATUS_IS_OK(status)) {
1726 END_PROFILE(SMBctemp);
1727 return ERROR_NT(status);
1730 status = check_name(conn, fname);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 END_PROFILE(SMBctemp);
1733 return ERROR_NT(status);
1736 tmpfd = smb_mkstemp(fname);
1738 END_PROFILE(SMBctemp);
1739 return(UNIXERROR(ERRDOS,ERRnoaccess));
1742 SMB_VFS_STAT(conn,fname,&sbuf);
1744 /* We should fail if file does not exist. */
1745 status = open_file_ntcreate(conn,fname,&sbuf,
1746 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1747 FILE_SHARE_READ|FILE_SHARE_WRITE,
1754 /* close fd from smb_mkstemp() */
1757 if (!NT_STATUS_IS_OK(status)) {
1758 END_PROFILE(SMBctemp);
1759 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1760 /* We have re-scheduled this call. */
1763 return ERROR_OPEN(status);
1766 outsize = set_message(outbuf,1,0,True);
1767 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1769 /* the returned filename is relative to the directory */
1770 s = strrchr_m(fname, '/');
1777 p = smb_buf(outbuf);
1779 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1780 thing in the byte section. JRA */
1781 SSVALS(p, 0, -1); /* what is this? not in spec */
1783 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1785 outsize = set_message_end(outbuf, p);
1787 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1788 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1791 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1792 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1795 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1796 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1797 (unsigned int)sbuf.st_mode ) );
1799 END_PROFILE(SMBctemp);
1803 /*******************************************************************
1804 Check if a user is allowed to rename a file.
1805 ********************************************************************/
1807 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open)
1813 if (!CAN_WRITE(conn)) {
1814 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1817 fmode = dos_mode(conn,fname,pst);
1818 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1819 return NT_STATUS_NO_SUCH_FILE;
1822 if (S_ISDIR(pst->st_mode)) {
1823 return NT_STATUS_OK;
1826 status = open_file_ntcreate(conn, fname, pst,
1828 /* If we're checking our fsp don't deny for delete. */
1830 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE :
1831 FILE_SHARE_READ|FILE_SHARE_WRITE,
1834 FILE_ATTRIBUTE_NORMAL,
1838 if (!NT_STATUS_IS_OK(status)) {
1841 close_file(fsp,NORMAL_CLOSE);
1842 return NT_STATUS_OK;
1845 /*******************************************************************
1846 Check if a user is allowed to delete a file.
1847 ********************************************************************/
1849 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1850 uint32 dirtype, BOOL can_defer)
1852 SMB_STRUCT_STAT sbuf;
1855 uint32 dirtype_orig = dirtype;
1858 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1860 if (!CAN_WRITE(conn)) {
1861 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1864 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1865 return map_nt_error_from_unix(errno);
1868 fattr = dos_mode(conn,fname,&sbuf);
1870 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1871 dirtype = aDIR|aARCH|aRONLY;
1874 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1876 return NT_STATUS_NO_SUCH_FILE;
1879 if (!dir_check_ftype(conn, fattr, dirtype)) {
1881 return NT_STATUS_FILE_IS_A_DIRECTORY;
1883 return NT_STATUS_NO_SUCH_FILE;
1886 if (dirtype_orig & 0x8000) {
1887 /* These will never be set for POSIX. */
1888 return NT_STATUS_NO_SUCH_FILE;
1892 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1893 return NT_STATUS_FILE_IS_A_DIRECTORY;
1896 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1897 return NT_STATUS_NO_SUCH_FILE;
1900 if (dirtype & 0xFF00) {
1901 /* These will never be set for POSIX. */
1902 return NT_STATUS_NO_SUCH_FILE;
1907 return NT_STATUS_NO_SUCH_FILE;
1910 /* Can't delete a directory. */
1912 return NT_STATUS_FILE_IS_A_DIRECTORY;
1917 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1918 return NT_STATUS_OBJECT_NAME_INVALID;
1919 #endif /* JRATEST */
1921 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1923 On a Windows share, a file with read-only dosmode can be opened with
1924 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1925 fails with NT_STATUS_CANNOT_DELETE error.
1927 This semantic causes a problem that a user can not
1928 rename a file with read-only dosmode on a Samba share
1929 from a Windows command prompt (i.e. cmd.exe, but can rename
1930 from Windows Explorer).
1933 if (!lp_delete_readonly(SNUM(conn))) {
1934 if (fattr & aRONLY) {
1935 return NT_STATUS_CANNOT_DELETE;
1939 /* On open checks the open itself will check the share mode, so
1940 don't do it here as we'll get it wrong. */
1942 status = open_file_ntcreate(conn, fname, &sbuf,
1947 FILE_ATTRIBUTE_NORMAL,
1948 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1951 if (NT_STATUS_IS_OK(status)) {
1952 close_file(fsp,NORMAL_CLOSE);
1957 /****************************************************************************
1958 The guts of the unlink command, split out so it may be called by the NT SMB
1960 ****************************************************************************/
1962 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1963 char *name, BOOL has_wild, BOOL can_defer)
1969 NTSTATUS status = NT_STATUS_OK;
1970 SMB_STRUCT_STAT sbuf;
1972 *directory = *mask = 0;
1974 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1975 if (!NT_STATUS_IS_OK(status)) {
1979 p = strrchr_m(name,'/');
1981 pstrcpy(directory,".");
1985 pstrcpy(directory,name);
1990 * We should only check the mangled cache
1991 * here if unix_convert failed. This means
1992 * that the path in 'mask' doesn't exist
1993 * on the file system and so we need to look
1994 * for a possible mangle. This patch from
1995 * Tine Smukavec <valentin.smukavec@hermes.si>.
1998 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1999 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2002 pstrcat(directory,"/");
2003 pstrcat(directory,mask);
2005 dirtype = FILE_ATTRIBUTE_NORMAL;
2008 status = check_name(conn, directory);
2009 if (!NT_STATUS_IS_OK(status)) {
2013 status = can_delete(conn,directory,dirtype,can_defer);
2014 if (!NT_STATUS_IS_OK(status)) {
2018 if (SMB_VFS_UNLINK(conn,directory) == 0) {
2020 notify_fname(conn, NOTIFY_ACTION_REMOVED,
2021 FILE_NOTIFY_CHANGE_FILE_NAME,
2025 struct smb_Dir *dir_hnd = NULL;
2029 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2030 return NT_STATUS_OBJECT_NAME_INVALID;
2033 if (strequal(mask,"????????.???")) {
2037 status = check_name(conn, directory);
2038 if (!NT_STATUS_IS_OK(status)) {
2042 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2043 if (dir_hnd == NULL) {
2044 return map_nt_error_from_unix(errno);
2047 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2048 the pattern matches against the long name, otherwise the short name
2049 We don't implement this yet XXXX
2052 status = NT_STATUS_NO_SUCH_FILE;
2054 while ((dname = ReadDirName(dir_hnd, &offset))) {
2057 pstrcpy(fname,dname);
2059 if (!is_visible_file(conn, directory, dname, &st, True)) {
2063 /* Quick check for "." and ".." */
2064 if (fname[0] == '.') {
2065 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2070 if(!mask_match(fname, mask, conn->case_sensitive)) {
2074 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2076 status = check_name(conn, fname);
2077 if (!NT_STATUS_IS_OK(status)) {
2082 status = can_delete(conn, fname, dirtype, can_defer);
2083 if (!NT_STATUS_IS_OK(status)) {
2086 if (SMB_VFS_UNLINK(conn,fname) == 0) {
2088 DEBUG(3,("unlink_internals: succesful unlink "
2090 notify_fname(conn, NOTIFY_ACTION_REMOVED,
2091 FILE_NOTIFY_CHANGE_FILE_NAME,
2099 if (count == 0 && NT_STATUS_IS_OK(status)) {
2100 status = map_nt_error_from_unix(errno);
2106 /****************************************************************************
2108 ****************************************************************************/
2110 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2117 BOOL path_contains_wcard = False;
2119 START_PROFILE(SMBunlink);
2121 dirtype = SVAL(inbuf,smb_vwv0);
2123 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2124 if (!NT_STATUS_IS_OK(status)) {
2125 END_PROFILE(SMBunlink);
2126 return ERROR_NT(status);
2129 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 END_PROFILE(SMBunlink);
2132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2133 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2135 return ERROR_NT(status);
2138 DEBUG(3,("reply_unlink : %s\n",name));
2140 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2142 if (!NT_STATUS_IS_OK(status)) {
2143 END_PROFILE(SMBunlink);
2144 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2145 /* We have re-scheduled this call. */
2148 return ERROR_NT(status);
2151 outsize = set_message(outbuf,0,0,False);
2153 END_PROFILE(SMBunlink);
2157 /****************************************************************************
2159 ****************************************************************************/
2161 static void fail_readraw(void)
2164 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2166 exit_server_cleanly(errstr);
2169 #if defined(WITH_SENDFILE)
2170 /****************************************************************************
2171 Fake (read/write) sendfile. Returns -1 on read or write fail.
2172 ****************************************************************************/
2174 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2178 /* Paranioa check... */
2179 if (nread > bufsize) {
2184 ret = read_file(fsp,buf,startpos,nread);
2190 /* If we had a short read, fill with zeros. */
2192 memset(buf, '\0', nread - ret);
2195 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2199 return (ssize_t)nread;
2203 /****************************************************************************
2204 Use sendfile in readbraw.
2205 ****************************************************************************/
2207 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2208 ssize_t mincount, char *outbuf, int out_buffsize)
2212 #if defined(WITH_SENDFILE)
2214 * We can only use sendfile on a non-chained packet
2215 * but we can use on a non-oplocked file. tridge proved this
2216 * on a train in Germany :-). JRA.
2217 * reply_readbraw has already checked the length.
2220 if ( (chain_size == 0) && (nread > 0) &&
2221 (fsp->wcp == NULL) && (fsp->is_sendfile_capable) ) {
2224 _smb_setlen(outbuf,nread);
2225 header.data = (uint8 *)outbuf;
2229 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2230 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2231 if (errno == ENOSYS) {
2232 goto normal_readbraw;
2236 * Special hack for broken Linux with no working sendfile. If we
2237 * return EINTR we sent the header but not the rest of the data.
2238 * Fake this up by doing read/write calls.
2240 if (errno == EINTR) {
2241 /* Ensure we don't do this again. */
2242 set_use_sendfile(SNUM(conn), False);
2243 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2245 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2246 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2247 fsp->fsp_name, strerror(errno) ));
2248 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2253 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2254 fsp->fsp_name, strerror(errno) ));
2255 exit_server_cleanly("send_file_readbraw sendfile failed");
2266 ret = read_file(fsp,outbuf+4,startpos,nread);
2267 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2276 _smb_setlen(outbuf,ret);
2277 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2281 /****************************************************************************
2282 Reply to a readbraw (core+ protocol).
2283 ****************************************************************************/
2285 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2287 ssize_t maxcount,mincount;
2290 char *header = outbuf;
2292 START_PROFILE(SMBreadbraw);
2294 if (srv_is_signing_active()) {
2295 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2299 * Special check if an oplock break has been issued
2300 * and the readraw request croses on the wire, we must
2301 * return a zero length response here.
2304 fsp = file_fsp(inbuf,smb_vwv0);
2306 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2308 * fsp could be NULL here so use the value from the packet. JRA.
2310 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2311 _smb_setlen(header,0);
2312 if (write_data(smbd_server_fd(),header,4) != 4)
2314 END_PROFILE(SMBreadbraw);
2318 CHECK_FSP(fsp,conn);
2320 flush_write_cache(fsp, READRAW_FLUSH);
2322 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2323 if(CVAL(inbuf,smb_wct) == 10) {
2325 * This is a large offset (64 bit) read.
2327 #ifdef LARGE_SMB_OFF_T
2329 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2331 #else /* !LARGE_SMB_OFF_T */
2334 * Ensure we haven't been sent a >32 bit offset.
2337 if(IVAL(inbuf,smb_vwv8) != 0) {
2338 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2339 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2340 _smb_setlen(header,0);
2341 if (write_data(smbd_server_fd(),header,4) != 4)
2343 END_PROFILE(SMBreadbraw);
2347 #endif /* LARGE_SMB_OFF_T */
2350 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2351 _smb_setlen(header,0);
2352 if (write_data(smbd_server_fd(),header,4) != 4)
2354 END_PROFILE(SMBreadbraw);
2358 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2359 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2361 /* ensure we don't overrun the packet size */
2362 maxcount = MIN(65535,maxcount);
2364 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2368 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2372 if (startpos >= size) {
2375 nread = MIN(maxcount,(size - startpos));
2379 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2380 if (nread < mincount)
2384 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2385 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2387 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2389 DEBUG(5,("readbraw finished\n"));
2390 END_PROFILE(SMBreadbraw);
2395 #define DBGC_CLASS DBGC_LOCKING
2397 /****************************************************************************
2398 Reply to a lockread (core+ protocol).
2399 ****************************************************************************/
2401 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2409 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2410 struct byte_range_lock *br_lck = NULL;
2411 START_PROFILE(SMBlockread);
2413 CHECK_FSP(fsp,conn);
2414 if (!CHECK_READ(fsp,inbuf)) {
2415 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2418 release_level_2_oplocks_on_change(fsp);
2420 numtoread = SVAL(inbuf,smb_vwv1);
2421 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2423 outsize = set_message(outbuf,5,3,True);
2424 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2425 data = smb_buf(outbuf) + 3;
2428 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2429 * protocol request that predates the read/write lock concept.
2430 * Thus instead of asking for a read lock here we need to ask
2431 * for a write lock. JRA.
2432 * Note that the requested lock size is unaffected by max_recv.
2435 br_lck = do_lock(fsp,
2436 (uint32)SVAL(inbuf,smb_pid),
2437 (SMB_BIG_UINT)numtoread,
2438 (SMB_BIG_UINT)startpos,
2441 False, /* Non-blocking lock. */
2444 TALLOC_FREE(br_lck);
2446 if (NT_STATUS_V(status)) {
2447 END_PROFILE(SMBlockread);
2448 return ERROR_NT(status);
2452 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2455 if (numtoread > max_recv) {
2456 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2457 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2458 (unsigned int)numtoread, (unsigned int)max_recv ));
2459 numtoread = MIN(numtoread,max_recv);
2461 nread = read_file(fsp,data,startpos,numtoread);
2464 END_PROFILE(SMBlockread);
2465 return(UNIXERROR(ERRDOS,ERRnoaccess));
2469 SSVAL(outbuf,smb_vwv0,nread);
2470 SSVAL(outbuf,smb_vwv5,nread+3);
2471 SSVAL(smb_buf(outbuf),1,nread);
2473 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2474 fsp->fnum, (int)numtoread, (int)nread));
2476 END_PROFILE(SMBlockread);
2481 #define DBGC_CLASS DBGC_ALL
2483 /****************************************************************************
2485 ****************************************************************************/
2487 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2494 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2495 START_PROFILE(SMBread);
2497 CHECK_FSP(fsp,conn);
2498 if (!CHECK_READ(fsp,inbuf)) {
2499 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2502 numtoread = SVAL(inbuf,smb_vwv1);
2503 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2505 outsize = set_message(outbuf,5,3,True);
2506 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2508 * The requested read size cannot be greater than max_recv. JRA.
2510 if (numtoread > max_recv) {
2511 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2512 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2513 (unsigned int)numtoread, (unsigned int)max_recv ));
2514 numtoread = MIN(numtoread,max_recv);
2517 data = smb_buf(outbuf) + 3;
2519 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2520 END_PROFILE(SMBread);
2521 return ERROR_DOS(ERRDOS,ERRlock);
2525 nread = read_file(fsp,data,startpos,numtoread);
2528 END_PROFILE(SMBread);
2529 return(UNIXERROR(ERRDOS,ERRnoaccess));
2533 SSVAL(outbuf,smb_vwv0,nread);
2534 SSVAL(outbuf,smb_vwv5,nread+3);
2535 SCVAL(smb_buf(outbuf),0,1);
2536 SSVAL(smb_buf(outbuf),1,nread);
2538 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2539 fsp->fnum, (int)numtoread, (int)nread ) );
2541 END_PROFILE(SMBread);
2545 /****************************************************************************
2546 Reply to a read and X - possibly using sendfile.
2547 ****************************************************************************/
2549 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2550 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2554 char *data = smb_buf(outbuf);
2556 #if defined(WITH_SENDFILE)
2558 * We can only use sendfile on a non-chained packet
2559 * but we can use on a non-oplocked file. tridge proved this
2560 * on a train in Germany :-). JRA.
2563 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2564 (fsp->is_sendfile_capable) && (fsp->wcp == NULL) ) {
2565 SMB_STRUCT_STAT sbuf;
2568 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2569 return(UNIXERROR(ERRDOS,ERRnoaccess));
2571 if (startpos > sbuf.st_size)
2574 if (smb_maxcnt > (sbuf.st_size - startpos))
2575 smb_maxcnt = (sbuf.st_size - startpos);
2577 if (smb_maxcnt == 0)
2581 * Set up the packet header before send. We
2582 * assume here the sendfile will work (get the
2583 * correct amount of data).
2586 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2587 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2588 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2589 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2590 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2591 SCVAL(outbuf,smb_vwv0,0xFF);
2592 set_message(outbuf,12,smb_maxcnt,False);
2593 header.data = (uint8 *)outbuf;
2594 header.length = data - outbuf;
2597 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2598 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2599 if (errno == ENOSYS) {
2604 * Special hack for broken Linux with no working sendfile. If we
2605 * return EINTR we sent the header but not the rest of the data.
2606 * Fake this up by doing read/write calls.
2609 if (errno == EINTR) {
2610 /* Ensure we don't do this again. */
2611 set_use_sendfile(SNUM(conn), False);
2612 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2614 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2615 len_outbuf - (data-outbuf))) == -1) {
2616 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2617 fsp->fsp_name, strerror(errno) ));
2618 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2620 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2621 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2622 /* Returning -1 here means successful sendfile. */
2626 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2627 fsp->fsp_name, strerror(errno) ));
2628 exit_server_cleanly("send_file_readX sendfile failed");
2631 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2632 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2633 /* Returning -1 here means successful sendfile. */
2641 nread = read_file(fsp,data,startpos,smb_maxcnt);
2644 return(UNIXERROR(ERRDOS,ERRnoaccess));
2647 outsize = set_message(outbuf,12,nread,False);
2648 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2649 SSVAL(outbuf,smb_vwv5,nread);
2650 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2651 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2652 SSVAL(smb_buf(outbuf),-2,nread);
2654 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2655 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2657 /* Returning the number of bytes we want to send back - including header. */
2661 /****************************************************************************
2662 Reply to a read and X.
2663 ****************************************************************************/
2665 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2667 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2668 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2670 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2672 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2675 START_PROFILE(SMBreadX);
2677 /* If it's an IPC, pass off the pipe handler. */
2679 END_PROFILE(SMBreadX);
2680 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2683 CHECK_FSP(fsp,conn);
2684 if (!CHECK_READ(fsp,inbuf)) {
2685 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2688 set_message(outbuf,12,0,True);
2690 if (global_client_caps & CAP_LARGE_READX) {
2691 if (SVAL(inbuf,smb_vwv7) == 1) {
2692 smb_maxcnt |= (1<<16);
2694 if (smb_maxcnt > BUFFER_SIZE) {
2695 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2696 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2697 END_PROFILE(SMBreadX);
2698 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2702 if(CVAL(inbuf,smb_wct) == 12) {
2703 #ifdef LARGE_SMB_OFF_T
2705 * This is a large offset (64 bit) read.
2707 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2709 #else /* !LARGE_SMB_OFF_T */
2712 * Ensure we haven't been sent a >32 bit offset.
2715 if(IVAL(inbuf,smb_vwv10) != 0) {
2716 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2717 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2718 END_PROFILE(SMBreadX);
2719 return ERROR_DOS(ERRDOS,ERRbadaccess);
2722 #endif /* LARGE_SMB_OFF_T */
2726 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2727 END_PROFILE(SMBreadX);
2728 return ERROR_DOS(ERRDOS,ERRlock);
2731 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2732 END_PROFILE(SMBreadX);
2736 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2737 /* Only call chain_reply if not an error. */
2738 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2739 nread = chain_reply(inbuf,outbuf,length,bufsize);
2742 END_PROFILE(SMBreadX);
2746 /****************************************************************************
2747 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2748 ****************************************************************************/
2750 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2753 ssize_t total_written=0;
2754 size_t numtowrite=0;
2759 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2762 START_PROFILE(SMBwritebraw);
2764 if (srv_is_signing_active()) {
2765 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2768 CHECK_FSP(fsp,conn);
2769 if (!CHECK_WRITE(fsp)) {
2770 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2773 tcount = IVAL(inbuf,smb_vwv1);
2774 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2775 write_through = BITSETW(inbuf+smb_vwv7,0);
2777 /* We have to deal with slightly different formats depending
2778 on whether we are using the core+ or lanman1.0 protocol */
2780 if(Protocol <= PROTOCOL_COREPLUS) {
2781 numtowrite = SVAL(smb_buf(inbuf),-2);
2782 data = smb_buf(inbuf);
2784 numtowrite = SVAL(inbuf,smb_vwv10);
2785 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2788 /* force the error type */
2789 SCVAL(inbuf,smb_com,SMBwritec);
2790 SCVAL(outbuf,smb_com,SMBwritec);
2792 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2793 END_PROFILE(SMBwritebraw);
2794 return(ERROR_DOS(ERRDOS,ERRlock));
2798 nwritten = write_file(fsp,data,startpos,numtowrite);
2800 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2801 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2803 if (nwritten < (ssize_t)numtowrite) {
2804 END_PROFILE(SMBwritebraw);
2805 return(UNIXERROR(ERRHRD,ERRdiskfull));
2808 total_written = nwritten;
2810 /* Return a message to the redirector to tell it to send more bytes */
2811 SCVAL(outbuf,smb_com,SMBwritebraw);
2812 SSVALS(outbuf,smb_vwv0,-1);
2813 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2815 if (!send_smb(smbd_server_fd(),outbuf))
2816 exit_server_cleanly("reply_writebraw: send_smb failed.");
2818 /* Now read the raw data into the buffer and write it */
2819 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2820 exit_server_cleanly("secondary writebraw failed");
2823 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2824 numtowrite = smb_len(inbuf);
2826 /* Set up outbuf to return the correct return */
2827 outsize = set_message(outbuf,1,0,True);
2828 SCVAL(outbuf,smb_com,SMBwritec);
2830 if (numtowrite != 0) {
2832 if (numtowrite > BUFFER_SIZE) {
2833 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2834 (unsigned int)numtowrite ));
2835 exit_server_cleanly("secondary writebraw failed");
2838 if (tcount > nwritten+numtowrite) {
2839 DEBUG(3,("Client overestimated the write %d %d %d\n",
2840 (int)tcount,(int)nwritten,(int)numtowrite));
2843 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2844 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2846 exit_server_cleanly("secondary writebraw failed");
2849 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2850 if (nwritten == -1) {
2851 END_PROFILE(SMBwritebraw);
2852 return(UNIXERROR(ERRHRD,ERRdiskfull));
2855 if (nwritten < (ssize_t)numtowrite) {
2856 SCVAL(outbuf,smb_rcls,ERRHRD);
2857 SSVAL(outbuf,smb_err,ERRdiskfull);
2861 total_written += nwritten;
2864 SSVAL(outbuf,smb_vwv0,total_written);
2866 status = sync_file(conn, fsp, write_through);
2867 if (!NT_STATUS_IS_OK(status)) {
2868 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2869 fsp->fsp_name, nt_errstr(status) ));
2870 END_PROFILE(SMBwritebraw);
2871 return ERROR_NT(status);
2874 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2875 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2877 /* we won't return a status if write through is not selected - this follows what WfWg does */
2878 END_PROFILE(SMBwritebraw);
2879 if (!write_through && total_written==tcount) {
2881 #if RABBIT_PELLET_FIX
2883 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2884 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2886 if (!send_keepalive(smbd_server_fd()))
2887 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2896 #define DBGC_CLASS DBGC_LOCKING
2898 /****************************************************************************
2899 Reply to a writeunlock (core+).
2900 ****************************************************************************/
2902 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2903 int size, int dum_buffsize)
2905 ssize_t nwritten = -1;
2909 NTSTATUS status = NT_STATUS_OK;
2910 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2912 START_PROFILE(SMBwriteunlock);
2914 CHECK_FSP(fsp,conn);
2915 if (!CHECK_WRITE(fsp)) {
2916 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2919 numtowrite = SVAL(inbuf,smb_vwv1);
2920 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2921 data = smb_buf(inbuf) + 3;
2923 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2924 END_PROFILE(SMBwriteunlock);
2925 return ERROR_DOS(ERRDOS,ERRlock);
2928 /* The special X/Open SMB protocol handling of
2929 zero length writes is *NOT* done for
2931 if(numtowrite == 0) {
2934 nwritten = write_file(fsp,data,startpos,numtowrite);
2937 status = sync_file(conn, fsp, False /* write through */);
2938 if (!NT_STATUS_IS_OK(status)) {
2939 END_PROFILE(SMBwriteunlock);
2940 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
2941 fsp->fsp_name, nt_errstr(status) ));
2942 return ERROR_NT(status);
2945 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2946 END_PROFILE(SMBwriteunlock);
2947 return(UNIXERROR(ERRHRD,ERRdiskfull));
2951 status = do_unlock(fsp,
2952 (uint32)SVAL(inbuf,smb_pid),
2953 (SMB_BIG_UINT)numtowrite,
2954 (SMB_BIG_UINT)startpos,
2957 if (NT_STATUS_V(status)) {
2958 END_PROFILE(SMBwriteunlock);
2959 return ERROR_NT(status);
2963 outsize = set_message(outbuf,1,0,True);
2965 SSVAL(outbuf,smb_vwv0,nwritten);
2967 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2968 fsp->fnum, (int)numtowrite, (int)nwritten));
2970 END_PROFILE(SMBwriteunlock);
2975 #define DBGC_CLASS DBGC_ALL
2977 /****************************************************************************
2979 ****************************************************************************/
2981 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2984 ssize_t nwritten = -1;
2987 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2990 START_PROFILE(SMBwrite);
2992 /* If it's an IPC, pass off the pipe handler. */
2994 END_PROFILE(SMBwrite);
2995 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2998 CHECK_FSP(fsp,conn);
2999 if (!CHECK_WRITE(fsp)) {
3000 END_PROFILE(SMBwrite);
3001 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3004 numtowrite = SVAL(inbuf,smb_vwv1);
3005 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3006 data = smb_buf(inbuf) + 3;
3008 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3009 END_PROFILE(SMBwrite);
3010 return ERROR_DOS(ERRDOS,ERRlock);
3014 * X/Open SMB protocol says that if smb_vwv1 is
3015 * zero then the file size should be extended or
3016 * truncated to the size given in smb_vwv[2-3].
3019 if(numtowrite == 0) {
3021 * This is actually an allocate call, and set EOF. JRA.
3023 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3025 END_PROFILE(SMBwrite);
3026 return ERROR_NT(NT_STATUS_DISK_FULL);
3028 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3030 END_PROFILE(SMBwrite);
3031 return ERROR_NT(NT_STATUS_DISK_FULL);
3034 nwritten = write_file(fsp,data,startpos,numtowrite);
3036 status = sync_file(conn, fsp, False);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 END_PROFILE(SMBwrite);
3039 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3040 fsp->fsp_name, nt_errstr(status) ));
3041 return ERROR_NT(status);
3044 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3045 END_PROFILE(SMBwrite);
3046 return(UNIXERROR(ERRHRD,ERRdiskfull));
3049 outsize = set_message(outbuf,1,0,True);
3051 SSVAL(outbuf,smb_vwv0,nwritten);
3053 if (nwritten < (ssize_t)numtowrite) {
3054 SCVAL(outbuf,smb_rcls,ERRHRD);
3055 SSVAL(outbuf,smb_err,ERRdiskfull);
3058 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3060 END_PROFILE(SMBwrite);
3064 /****************************************************************************
3065 Reply to a write and X.
3066 ****************************************************************************/
3068 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3070 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3071 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3072 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3073 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3074 ssize_t nwritten = -1;
3075 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3076 unsigned int smblen = smb_len(inbuf);
3078 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3080 START_PROFILE(SMBwriteX);
3082 /* If it's an IPC, pass off the pipe handler. */
3084 END_PROFILE(SMBwriteX);
3085 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3088 CHECK_FSP(fsp,conn);
3089 if (!CHECK_WRITE(fsp)) {
3090 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3093 set_message(outbuf,6,0,True);
3095 /* Deal with possible LARGE_WRITEX */
3097 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3100 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3101 END_PROFILE(SMBwriteX);
3102 return ERROR_DOS(ERRDOS,ERRbadmem);
3105 data = smb_base(inbuf) + smb_doff;
3107 if(CVAL(inbuf,smb_wct) == 14) {
3108 #ifdef LARGE_SMB_OFF_T
3110 * This is a large offset (64 bit) write.
3112 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3114 #else /* !LARGE_SMB_OFF_T */
3117 * Ensure we haven't been sent a >32 bit offset.
3120 if(IVAL(inbuf,smb_vwv12) != 0) {
3121 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3122 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3123 END_PROFILE(SMBwriteX);
3124 return ERROR_DOS(ERRDOS,ERRbadaccess);
3127 #endif /* LARGE_SMB_OFF_T */
3130 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3131 END_PROFILE(SMBwriteX);
3132 return ERROR_DOS(ERRDOS,ERRlock);
3135 /* X/Open SMB protocol says that, unlike SMBwrite
3136 if the length is zero then NO truncation is
3137 done, just a write of zero. To truncate a file,
3140 if(numtowrite == 0) {
3144 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3145 fsp,data,startpos,numtowrite)) {
3146 END_PROFILE(SMBwriteX);
3150 nwritten = write_file(fsp,data,startpos,numtowrite);
3153 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3154 END_PROFILE(SMBwriteX);
3155 return(UNIXERROR(ERRHRD,ERRdiskfull));
3158 SSVAL(outbuf,smb_vwv2,nwritten);
3160 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3162 if (nwritten < (ssize_t)numtowrite) {
3163 SCVAL(outbuf,smb_rcls,ERRHRD);
3164 SSVAL(outbuf,smb_err,ERRdiskfull);
3167 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3168 fsp->fnum, (int)numtowrite, (int)nwritten));
3170 status = sync_file(conn, fsp, write_through);
3171 if (!NT_STATUS_IS_OK(status)) {
3172 END_PROFILE(SMBwriteX);
3173 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3174 fsp->fsp_name, nt_errstr(status) ));
3175 return ERROR_NT(status);
3178 END_PROFILE(SMBwriteX);
3179 return chain_reply(inbuf,outbuf,length,bufsize);
3182 /****************************************************************************
3184 ****************************************************************************/
3186 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3192 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3193 START_PROFILE(SMBlseek);
3195 CHECK_FSP(fsp,conn);
3197 flush_write_cache(fsp, SEEK_FLUSH);
3199 mode = SVAL(inbuf,smb_vwv1) & 3;
3200 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3201 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3210 res = fsp->fh->pos + startpos;
3221 if (umode == SEEK_END) {
3222 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3223 if(errno == EINVAL) {
3224 SMB_OFF_T current_pos = startpos;
3225 SMB_STRUCT_STAT sbuf;
3227 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3228 END_PROFILE(SMBlseek);
3229 return(UNIXERROR(ERRDOS,ERRnoaccess));
3232 current_pos += sbuf.st_size;
3234 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3239 END_PROFILE(SMBlseek);
3240 return(UNIXERROR(ERRDOS,ERRnoaccess));
3246 outsize = set_message(outbuf,2,0,True);
3247 SIVAL(outbuf,smb_vwv0,res);
3249 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3250 fsp->fnum, (double)startpos, (double)res, mode));
3252 END_PROFILE(SMBlseek);
3256 /****************************************************************************
3258 ****************************************************************************/
3260 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3262 int outsize = set_message(outbuf,0,0,False);
3263 uint16 fnum = SVAL(inbuf,smb_vwv0);
3264 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3265 START_PROFILE(SMBflush);
3268 CHECK_FSP(fsp,conn);
3271 file_sync_all(conn);
3273 NTSTATUS status = sync_file(conn, fsp, True);
3274 if (!NT_STATUS_IS_OK(status)) {
3275 END_PROFILE(SMBflush);
3276 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3277 fsp->fsp_name, nt_errstr(status) ));
3278 return ERROR_NT(status);
3282 DEBUG(3,("flush\n"));
3283 END_PROFILE(SMBflush);
3287 /****************************************************************************
3289 conn POINTER CAN BE NULL HERE !
3290 ****************************************************************************/
3292 int reply_exit(connection_struct *conn,
3293 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3296 START_PROFILE(SMBexit);
3298 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3300 outsize = set_message(outbuf,0,0,False);
3302 DEBUG(3,("exit\n"));
3304 END_PROFILE(SMBexit);
3308 /****************************************************************************
3309 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3310 ****************************************************************************/
3312 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3315 NTSTATUS status = NT_STATUS_OK;
3317 files_struct *fsp = NULL;
3318 START_PROFILE(SMBclose);
3320 outsize = set_message(outbuf,0,0,False);
3322 /* If it's an IPC, pass off to the pipe handler. */
3324 END_PROFILE(SMBclose);
3325 return reply_pipe_close(conn, inbuf,outbuf);
3328 fsp = file_fsp(inbuf,smb_vwv0);
3331 * We can only use CHECK_FSP if we know it's not a directory.
3334 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3335 END_PROFILE(SMBclose);
3336 return ERROR_DOS(ERRDOS,ERRbadfid);
3339 if(fsp->is_directory) {
3341 * Special case - close NT SMB directory handle.
3343 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3344 status = close_file(fsp,NORMAL_CLOSE);
3347 * Close ordinary file.
3350 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3351 fsp->fh->fd, fsp->fnum,
3352 conn->num_files_open));
3355 * Take care of any time sent in the close.
3358 fsp_set_pending_modtime(fsp,
3359 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3362 * close_file() returns the unix errno if an error
3363 * was detected on close - normally this is due to
3364 * a disk full error. If not then it was probably an I/O error.
3367 status = close_file(fsp,NORMAL_CLOSE);
3370 if(!NT_STATUS_IS_OK(status)) {
3371 END_PROFILE(SMBclose);
3372 return ERROR_NT(status);
3375 END_PROFILE(SMBclose);
3379 /****************************************************************************
3380 Reply to a writeclose (Core+ protocol).
3381 ****************************************************************************/
3383 int reply_writeclose(connection_struct *conn,
3384 char *inbuf,char *outbuf, int size, int dum_buffsize)
3387 ssize_t nwritten = -1;
3389 NTSTATUS close_status = NT_STATUS_OK;
3392 struct timespec mtime;
3393 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3394 START_PROFILE(SMBwriteclose);
3396 CHECK_FSP(fsp,conn);
3397 if (!CHECK_WRITE(fsp)) {
3398 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3401 numtowrite = SVAL(inbuf,smb_vwv1);
3402 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3403 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3404 data = smb_buf(inbuf) + 1;
3406 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3407 END_PROFILE(SMBwriteclose);
3408 return ERROR_DOS(ERRDOS,ERRlock);
3411 nwritten = write_file(fsp,data,startpos,numtowrite);
3413 set_filetime(conn, fsp->fsp_name, mtime);
3416 * More insanity. W2K only closes the file if writelen > 0.
3421 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3423 close_status = close_file(fsp,NORMAL_CLOSE);
3426 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3427 fsp->fnum, (int)numtowrite, (int)nwritten,
3428 conn->num_files_open));
3430 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3431 END_PROFILE(SMBwriteclose);
3432 return(UNIXERROR(ERRHRD,ERRdiskfull));
3435 if(!NT_STATUS_IS_OK(close_status)) {
3436 END_PROFILE(SMBwriteclose);
3437 return ERROR_NT(close_status);
3440 outsize = set_message(outbuf,1,0,True);
3442 SSVAL(outbuf,smb_vwv0,nwritten);
3443 END_PROFILE(SMBwriteclose);
3448 #define DBGC_CLASS DBGC_LOCKING
3450 /****************************************************************************
3452 ****************************************************************************/
3454 int reply_lock(connection_struct *conn,
3455 char *inbuf,char *outbuf, int length, int dum_buffsize)
3457 int outsize = set_message(outbuf,0,0,False);
3458 SMB_BIG_UINT count,offset;
3460 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3461 struct byte_range_lock *br_lck = NULL;
3463 START_PROFILE(SMBlock);
3465 CHECK_FSP(fsp,conn);
3467 release_level_2_oplocks_on_change(fsp);
3469 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3470 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3472 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3473 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3475 br_lck = do_lock(fsp,
3476 (uint32)SVAL(inbuf,smb_pid),
3481 False, /* Non-blocking lock. */
3485 TALLOC_FREE(br_lck);
3487 if (NT_STATUS_V(status)) {
3488 END_PROFILE(SMBlock);
3489 return ERROR_NT(status);
3492 END_PROFILE(SMBlock);
3496 /****************************************************************************
3498 ****************************************************************************/
3500 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3503 int outsize = set_message(outbuf,0,0,False);
3504 SMB_BIG_UINT count,offset;
3506 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3507 START_PROFILE(SMBunlock);
3509 CHECK_FSP(fsp,conn);
3511 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3512 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3514 status = do_unlock(fsp,
3515 (uint32)SVAL(inbuf,smb_pid),
3520 if (NT_STATUS_V(status)) {
3521 END_PROFILE(SMBunlock);
3522 return ERROR_NT(status);
3525 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3526 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3528 END_PROFILE(SMBunlock);
3533 #define DBGC_CLASS DBGC_ALL
3535 /****************************************************************************
3537 conn POINTER CAN BE NULL HERE !
3538 ****************************************************************************/
3540 int reply_tdis(connection_struct *conn,
3541 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3543 int outsize = set_message(outbuf,0,0,False);
3545 START_PROFILE(SMBtdis);
3547 vuid = SVAL(inbuf,smb_uid);
3550 DEBUG(4,("Invalid connection in tdis\n"));
3551 END_PROFILE(SMBtdis);
3552 return ERROR_DOS(ERRSRV,ERRinvnid);
3557 close_cnum(conn,vuid);
3559 END_PROFILE(SMBtdis);
3563 /****************************************************************************
3565 conn POINTER CAN BE NULL HERE !
3566 ****************************************************************************/
3568 int reply_echo(connection_struct *conn,
3569 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3571 int smb_reverb = SVAL(inbuf,smb_vwv0);
3573 unsigned int data_len = smb_buflen(inbuf);
3574 int outsize = set_message(outbuf,1,data_len,True);
3575 START_PROFILE(SMBecho);
3577 if (data_len > BUFFER_SIZE) {
3578 DEBUG(0,("reply_echo: data_len too large.\n"));
3579 END_PROFILE(SMBecho);
3583 /* copy any incoming data back out */
3585 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3587 if (smb_reverb > 100) {
3588 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3592 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3593 SSVAL(outbuf,smb_vwv0,seq_num);
3595 smb_setlen(outbuf,outsize - 4);
3598 if (!send_smb(smbd_server_fd(),outbuf))
3599 exit_server_cleanly("reply_echo: send_smb failed.");
3602 DEBUG(3,("echo %d times\n", smb_reverb));
3606 END_PROFILE(SMBecho);
3610 /****************************************************************************
3611 Reply to a printopen.
3612 ****************************************************************************/
3614 int reply_printopen(connection_struct *conn,
3615 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3621 START_PROFILE(SMBsplopen);
3623 if (!CAN_PRINT(conn)) {
3624 END_PROFILE(SMBsplopen);
3625 return ERROR_DOS(ERRDOS,ERRnoaccess);
3628 /* Open for exclusive use, write only. */
3629 status = print_fsp_open(conn, NULL, &fsp);
3631 if (!NT_STATUS_IS_OK(status)) {
3632 END_PROFILE(SMBsplopen);
3633 return(ERROR_NT(status));
3636 outsize = set_message(outbuf,1,0,True);
3637 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3639 DEBUG(3,("openprint fd=%d fnum=%d\n",
3640 fsp->fh->fd, fsp->fnum));
3642 END_PROFILE(SMBsplopen);
3646 /****************************************************************************
3647 Reply to a printclose.
3648 ****************************************************************************/
3650 int reply_printclose(connection_struct *conn,
3651 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3653 int outsize = set_message(outbuf,0,0,False);
3654 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3656 START_PROFILE(SMBsplclose);
3658 CHECK_FSP(fsp,conn);
3660 if (!CAN_PRINT(conn)) {
3661 END_PROFILE(SMBsplclose);
3662 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3665 DEBUG(3,("printclose fd=%d fnum=%d\n",
3666 fsp->fh->fd,fsp->fnum));
3668 status = close_file(fsp,NORMAL_CLOSE);
3670 if(!NT_STATUS_IS_OK(status)) {
3671 END_PROFILE(SMBsplclose);
3672 return ERROR_NT(status);
3675 END_PROFILE(SMBsplclose);
3679 /****************************************************************************
3680 Reply to a printqueue.
3681 ****************************************************************************/
3683 int reply_printqueue(connection_struct *conn,
3684 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3686 int outsize = set_message(outbuf,2,3,True);
3687 int max_count = SVAL(inbuf,smb_vwv0);
3688 int start_index = SVAL(inbuf,smb_vwv1);
3689 START_PROFILE(SMBsplretq);
3691 /* we used to allow the client to get the cnum wrong, but that
3692 is really quite gross and only worked when there was only
3693 one printer - I think we should now only accept it if they
3694 get it right (tridge) */
3695 if (!CAN_PRINT(conn)) {
3696 END_PROFILE(SMBsplretq);
3697 return ERROR_DOS(ERRDOS,ERRnoaccess);
3700 SSVAL(outbuf,smb_vwv0,0);
3701 SSVAL(outbuf,smb_vwv1,0);
3702 SCVAL(smb_buf(outbuf),0,1);
3703 SSVAL(smb_buf(outbuf),1,0);
3705 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3706 start_index, max_count));
3709 print_queue_struct *queue = NULL;
3710 print_status_struct status;
3711 char *p = smb_buf(outbuf) + 3;
3712 int count = print_queue_status(SNUM(conn), &queue, &status);
3713 int num_to_get = ABS(max_count);
3714 int first = (max_count>0?start_index:start_index+max_count+1);
3720 num_to_get = MIN(num_to_get,count-first);
3723 for (i=first;i<first+num_to_get;i++) {
3724 srv_put_dos_date2(p,0,queue[i].time);
3725 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3726 SSVAL(p,5, queue[i].job);
3727 SIVAL(p,7,queue[i].size);
3729 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3734 outsize = set_message(outbuf,2,28*count+3,False);
3735 SSVAL(outbuf,smb_vwv0,count);
3736 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3737 SCVAL(smb_buf(outbuf),0,1);
3738 SSVAL(smb_buf(outbuf),1,28*count);
3743 DEBUG(3,("%d entries returned in queue\n",count));
3746 END_PROFILE(SMBsplretq);
3750 /****************************************************************************
3751 Reply to a printwrite.
3752 ****************************************************************************/
3754 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3757 int outsize = set_message(outbuf,0,0,False);
3759 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3761 START_PROFILE(SMBsplwr);
3763 if (!CAN_PRINT(conn)) {
3764 END_PROFILE(SMBsplwr);
3765 return ERROR_DOS(ERRDOS,ERRnoaccess);
3768 CHECK_FSP(fsp,conn);
3769 if (!CHECK_WRITE(fsp)) {
3770 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3773 numtowrite = SVAL(smb_buf(inbuf),1);
3774 data = smb_buf(inbuf) + 3;
3776 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3777 END_PROFILE(SMBsplwr);
3778 return(UNIXERROR(ERRHRD,ERRdiskfull));
3781 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3783 END_PROFILE(SMBsplwr);
3787 /****************************************************************************
3789 ****************************************************************************/
3791 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3796 SMB_STRUCT_STAT sbuf;
3798 START_PROFILE(SMBmkdir);
3800 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3801 if (!NT_STATUS_IS_OK(status)) {
3802 END_PROFILE(SMBmkdir);
3803 return ERROR_NT(status);
3806 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3807 if (!NT_STATUS_IS_OK(status)) {
3808 END_PROFILE(SMBmkdir);
3809 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3810 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3812 return ERROR_NT(status);
3815 status = unix_convert(conn, directory, False, NULL, &sbuf);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 END_PROFILE(SMBmkdir);
3818 return ERROR_NT(status);
3821 status = check_name(conn, directory);
3822 if (!NT_STATUS_IS_OK(status)) {
3823 END_PROFILE(SMBmkdir);
3824 return ERROR_NT(status);
3827 status = create_directory(conn, directory);
3829 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3831 if (!NT_STATUS_IS_OK(status)) {
3833 if (!use_nt_status()
3834 && NT_STATUS_EQUAL(status,
3835 NT_STATUS_OBJECT_NAME_COLLISION)) {
3837 * Yes, in the DOS error code case we get a
3838 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3839 * samba4 torture test.
3841 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3844 END_PROFILE(SMBmkdir);
3845 return ERROR_NT(status);
3848 outsize = set_message(outbuf,0,0,False);
3850 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3852 END_PROFILE(SMBmkdir);
3856 /****************************************************************************
3857 Static function used by reply_rmdir to delete an entire directory
3858 tree recursively. Return True on ok, False on fail.
3859 ****************************************************************************/
3861 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3863 const char *dname = NULL;
3866 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3871 while((dname = ReadDirName(dir_hnd, &offset))) {
3875 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3878 if (!is_visible_file(conn, directory, dname, &st, False))
3881 /* Construct the full name. */
3882 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3888 pstrcpy(fullname, directory);
3889 pstrcat(fullname, "/");
3890 pstrcat(fullname, dname);
3892 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3897 if(st.st_mode & S_IFDIR) {
3898 if(!recursive_rmdir(conn, fullname)) {
3902 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3906 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3915 /****************************************************************************
3916 The internals of the rmdir code - called elsewhere.
3917 ****************************************************************************/
3919 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3924 /* Might be a symlink. */
3925 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
3926 return map_nt_error_from_unix(errno);
3929 if (S_ISLNK(st.st_mode)) {
3930 /* Is what it points to a directory ? */
3931 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
3932 return map_nt_error_from_unix(errno);
3934 if (!(S_ISDIR(st.st_mode))) {
3935 return NT_STATUS_NOT_A_DIRECTORY;
3937 ret = SMB_VFS_UNLINK(conn,directory);
3939 ret = SMB_VFS_RMDIR(conn,directory);
3942 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3943 FILE_NOTIFY_CHANGE_DIR_NAME,
3945 return NT_STATUS_OK;
3948 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3950 * Check to see if the only thing in this directory are
3951 * vetoed files/directories. If so then delete them and
3952 * retry. If we fail to delete any of them (and we *don't*
3953 * do a recursive delete) then fail the rmdir.
3957 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3959 if(dir_hnd == NULL) {
3964 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3965 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3967 if (!is_visible_file(conn, directory, dname, &st, False))
3969 if(!IS_VETO_PATH(conn, dname)) {
3976 /* We only have veto files/directories. Recursive delete. */
3978 RewindDir(dir_hnd,&dirpos);
3979 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3982 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3984 if (!is_visible_file(conn, directory, dname, &st, False))
3987 /* Construct the full name. */
3988 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3993 pstrcpy(fullname, directory);
3994 pstrcat(fullname, "/");
3995 pstrcat(fullname, dname);
3997 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3999 if(st.st_mode & S_IFDIR) {
4000 if(lp_recursive_veto_delete(SNUM(conn))) {
4001 if(!recursive_rmdir(conn, fullname))
4004 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4006 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4010 /* Retry the rmdir */
4011 ret = SMB_VFS_RMDIR(conn,directory);
4017 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4018 "%s\n", directory,strerror(errno)));
4019 return map_nt_error_from_unix(errno);
4022 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4023 FILE_NOTIFY_CHANGE_DIR_NAME,
4026 return NT_STATUS_OK;
4029 /****************************************************************************
4031 ****************************************************************************/
4033 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4037 SMB_STRUCT_STAT sbuf;
4039 START_PROFILE(SMBrmdir);
4041 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
4042 if (!NT_STATUS_IS_OK(status)) {
4043 END_PROFILE(SMBrmdir);
4044 return ERROR_NT(status);
4047 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4048 if (!NT_STATUS_IS_OK(status)) {
4049 END_PROFILE(SMBrmdir);
4050 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4051 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4053 return ERROR_NT(status);
4056 status = unix_convert(conn, directory, False, NULL, &sbuf);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 END_PROFILE(SMBrmdir);
4059 return ERROR_NT(status);
4062 status = check_name(conn, directory);
4063 if (!NT_STATUS_IS_OK(status)) {
4064 END_PROFILE(SMBrmdir);
4065 return ERROR_NT(status);
4068 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4069 status = rmdir_internals(conn, directory);
4070 if (!NT_STATUS_IS_OK(status)) {
4071 END_PROFILE(SMBrmdir);
4072 return ERROR_NT(status);
4075 outsize = set_message(outbuf,0,0,False);
4077 DEBUG( 3, ( "rmdir %s\n", directory ) );
4079 END_PROFILE(SMBrmdir);
4083 /*******************************************************************
4084 Resolve wildcards in a filename rename.
4085 Note that name is in UNIX charset and thus potentially can be more
4086 than fstring buffer (255 bytes) especially in default UTF-8 case.
4087 Therefore, we use pstring inside and all calls should ensure that
4088 name2 is at least pstring-long (they do already)
4089 ********************************************************************/
4091 static BOOL resolve_wildcards(const char *name1, char *name2)
4093 pstring root1,root2;
4095 char *p,*p2, *pname1, *pname2;
4096 int available_space, actual_space;
4098 pname1 = strrchr_m(name1,'/');
4099 pname2 = strrchr_m(name2,'/');
4101 if (!pname1 || !pname2)
4104 pstrcpy(root1,pname1);
4105 pstrcpy(root2,pname2);
4106 p = strrchr_m(root1,'.');
4113 p = strrchr_m(root2,'.');
4127 } else if (*p2 == '*') {
4143 } else if (*p2 == '*') {
4153 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4156 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4157 if (actual_space >= available_space - 1) {
4158 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4159 actual_space - available_space));
4162 pstrcpy_base(pname2, root2, name2);
4168 /****************************************************************************
4169 Ensure open files have their names updated. Updated to notify other smbd's
4171 ****************************************************************************/
4173 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4174 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4177 BOOL did_rename = False;
4179 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4180 /* fsp_name is a relative path under the fsp. To change this for other
4181 sharepaths we need to manipulate relative paths. */
4182 /* TODO - create the absolute path and manipulate the newname
4183 relative to the sharepath. */
4184 if (fsp->conn != conn) {
4187 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4188 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4189 fsp->fsp_name, newname ));
4190 string_set(&fsp->fsp_name, newname);
4195 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4196 (unsigned int)dev, (double)inode, newname ));
4199 /* Send messages to all smbd's (not ourself) that the name has changed. */
4200 rename_share_filename(lck, conn->connectpath, newname);
4203 /****************************************************************************
4204 We need to check if the source path is a parent directory of the destination
4205 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4206 refuse the rename with a sharing violation. Under UNIX the above call can
4207 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4208 probably need to check that the client is a Windows one before disallowing
4209 this as a UNIX client (one with UNIX extensions) can know the source is a
4210 symlink and make this decision intelligently. Found by an excellent bug
4211 report from <AndyLiebman@aol.com>.
4212 ****************************************************************************/
4214 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4216 const char *psrc = src;
4217 const char *pdst = dest;
4220 if (psrc[0] == '.' && psrc[1] == '/') {
4223 if (pdst[0] == '.' && pdst[1] == '/') {
4226 if ((slen = strlen(psrc)) > strlen(pdst)) {
4229 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4232 /****************************************************************************
4233 Rename an open file - given an fsp.
4234 ****************************************************************************/
4236 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4238 SMB_STRUCT_STAT sbuf;
4239 pstring newname_last_component;
4240 NTSTATUS status = NT_STATUS_OK;
4242 struct share_mode_lock *lck = NULL;
4246 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4248 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4250 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4254 status = check_name(conn, newname);
4255 if (!NT_STATUS_IS_OK(status)) {
4259 /* Ensure newname contains a '/' */
4260 if(strrchr_m(newname,'/') == 0) {
4263 pstrcpy(tmpstr, "./");
4264 pstrcat(tmpstr, newname);
4265 pstrcpy(newname, tmpstr);
4269 * Check for special case with case preserving and not
4270 * case sensitive. If the old last component differs from the original
4271 * last component only by case, then we should allow
4272 * the rename (user is trying to change the case of the
4276 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4277 strequal(newname, fsp->fsp_name)) {
4279 pstring newname_modified_last_component;
4282 * Get the last component of the modified name.
4283 * Note that we guarantee that newname contains a '/'
4286 p = strrchr_m(newname,'/');
4287 pstrcpy(newname_modified_last_component,p+1);
4289 if(strcsequal(newname_modified_last_component,
4290 newname_last_component) == False) {
4292 * Replace the modified last component with
4295 pstrcpy(p+1, newname_last_component);
4300 * If the src and dest names are identical - including case,
4301 * don't do the rename, just return success.
4304 if (strcsequal(fsp->fsp_name, newname)) {
4305 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4307 return NT_STATUS_OK;
4310 dest_exists = vfs_object_exist(conn,newname,NULL);
4312 if(!replace_if_exists && dest_exists) {
4313 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4314 fsp->fsp_name,newname));
4315 return NT_STATUS_OBJECT_NAME_COLLISION;
4318 /* Ensure we have a valid stat struct for the source. */
4319 if (fsp->fh->fd != -1) {
4320 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4321 return map_nt_error_from_unix(errno);
4324 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4325 return map_nt_error_from_unix(errno);
4329 status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
4331 if (!NT_STATUS_IS_OK(status)) {
4332 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4333 nt_errstr(status), fsp->fsp_name,newname));
4334 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4335 status = NT_STATUS_ACCESS_DENIED;
4339 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4340 return NT_STATUS_ACCESS_DENIED;
4343 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4345 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4346 uint32 create_options = fsp->fh->private_options;
4348 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4349 fsp->fsp_name,newname));
4351 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4354 * A rename acts as a new file create w.r.t. allowing an initial delete
4355 * on close, probably because in Windows there is a new handle to the
4356 * new file. If initial delete on close was requested but not
4357 * originally set, we need to set it here. This is probably not 100% correct,
4358 * but will work for the CIFSFS client which in non-posix mode
4359 * depends on these semantics. JRA.
4362 set_allow_initial_delete_on_close(lck, fsp, True);
4364 if (create_options & FILE_DELETE_ON_CLOSE) {
4365 status = can_set_delete_on_close(fsp, True, 0);
4367 if (NT_STATUS_IS_OK(status)) {
4368 /* Note that here we set the *inital* delete on close flag,
4369 * not the regular one. The magic gets handled in close. */
4370 fsp->initial_delete_on_close = True;
4374 return NT_STATUS_OK;
4379 if (errno == ENOTDIR || errno == EISDIR) {
4380 status = NT_STATUS_OBJECT_NAME_COLLISION;
4382 status = map_nt_error_from_unix(errno);
4385 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4386 nt_errstr(status), fsp->fsp_name,newname));
4392 * Do the notify calls from a rename
4395 static void notify_rename(connection_struct *conn, BOOL is_dir,
4396 const char *oldpath, const char *newpath)
4398 char *olddir, *newdir;
4399 const char *oldname, *newname;
4402 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4403 : FILE_NOTIFY_CHANGE_FILE_NAME;
4405 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4406 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4407 TALLOC_FREE(olddir);
4411 if (strcmp(olddir, newdir) == 0) {
4412 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4413 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4416 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4417 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4419 TALLOC_FREE(olddir);
4420 TALLOC_FREE(newdir);
4422 /* this is a strange one. w2k3 gives an additional event for
4423 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4424 files, but not directories */
4426 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4427 FILE_NOTIFY_CHANGE_ATTRIBUTES
4428 |FILE_NOTIFY_CHANGE_CREATION,
4433 /****************************************************************************
4434 The guts of the rename command, split out so it may be called by the NT SMB
4436 ****************************************************************************/
4438 NTSTATUS rename_internals(connection_struct *conn,
4442 BOOL replace_if_exists,
4448 pstring last_component_src;
4449 pstring last_component_dest;
4452 NTSTATUS status = NT_STATUS_OK;
4453 SMB_STRUCT_STAT sbuf1, sbuf2;
4454 struct share_mode_lock *lck = NULL;
4455 struct smb_Dir *dir_hnd = NULL;
4460 *directory = *mask = 0;
4465 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4466 if (!NT_STATUS_IS_OK(status)) {
4470 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4471 if (!NT_STATUS_IS_OK(status)) {
4476 * Split the old name into directory and last component
4477 * strings. Note that unix_convert may have stripped off a
4478 * leading ./ from both name and newname if the rename is
4479 * at the root of the share. We need to make sure either both
4480 * name and newname contain a / character or neither of them do
4481 * as this is checked in resolve_wildcards().
4484 p = strrchr_m(name,'/');
4486 pstrcpy(directory,".");
4490 pstrcpy(directory,name);
4492 *p = '/'; /* Replace needed for exceptional test below. */
4496 * We should only check the mangled cache
4497 * here if unix_convert failed. This means
4498 * that the path in 'mask' doesn't exist
4499 * on the file system and so we need to look
4500 * for a possible mangle. This patch from
4501 * Tine Smukavec <valentin.smukavec@hermes.si>.
4504 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4505 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4508 if (!src_has_wild) {
4510 * No wildcards - just process the one file.
4512 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4514 /* Add a terminating '/' to the directory name. */
4515 pstrcat(directory,"/");
4516 pstrcat(directory,mask);
4518 /* Ensure newname contains a '/' also */
4519 if(strrchr_m(newname,'/') == 0) {
4522 pstrcpy(tmpstr, "./");
4523 pstrcat(tmpstr, newname);
4524 pstrcpy(newname, tmpstr);
4527 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4528 "case_preserve = %d, short case preserve = %d, "
4529 "directory = %s, newname = %s, "
4530 "last_component_dest = %s, is_8_3 = %d\n",
4531 conn->case_sensitive, conn->case_preserve,
4532 conn->short_case_preserve, directory,
4533 newname, last_component_dest, is_short_name));
4535 /* Ensure the source name is valid for us to access. */
4536 status = check_name(conn, directory);
4537 if (!NT_STATUS_IS_OK(status)) {
4541 /* The dest name still may have wildcards. */
4542 if (dest_has_wild) {
4543 if (!resolve_wildcards(directory,newname)) {
4544 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4545 directory,newname));
4546 return NT_STATUS_NO_MEMORY;
4551 * Check for special case with case preserving and not
4552 * case sensitive, if directory and newname are identical,
4553 * and the old last component differs from the original
4554 * last component only by case, then we should allow
4555 * the rename (user is trying to change the case of the
4558 if((conn->case_sensitive == False) &&
4559 (((conn->case_preserve == True) &&
4560 (is_short_name == False)) ||
4561 ((conn->short_case_preserve == True) &&
4562 (is_short_name == True))) &&
4563 strcsequal(directory, newname)) {
4564 pstring modified_last_component;
4567 * Get the last component of the modified name.
4568 * Note that we guarantee that newname contains a '/'
4571 p = strrchr_m(newname,'/');
4572 pstrcpy(modified_last_component,p+1);
4574 if(strcsequal(modified_last_component,
4575 last_component_dest) == False) {
4577 * Replace the modified last component with
4580 pstrcpy(p+1, last_component_dest);
4584 /* Ensure the dest name is valid for us to access. */
4585 status = check_name(conn, newname);
4586 if (!NT_STATUS_IS_OK(status)) {
4591 * The source object must exist.
4594 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4595 DEBUG(3, ("rename_internals: source doesn't exist "
4596 "doing rename %s -> %s\n",
4597 directory,newname));
4599 if (errno == ENOTDIR || errno == EISDIR
4600 || errno == ENOENT) {
4602 * Must return different errors depending on
4603 * whether the parent directory existed or
4607 p = strrchr_m(directory, '/');
4609 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4611 if (vfs_object_exist(conn, directory, NULL))
4612 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4613 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4615 status = map_nt_error_from_unix(errno);
4616 DEBUG(3, ("rename_internals: Error %s rename %s -> "
4617 "%s\n", nt_errstr(status), directory,
4623 status = can_rename(conn,directory,attrs,&sbuf1,False);
4625 if (!NT_STATUS_IS_OK(status)) {
4626 DEBUG(3,("rename_internals: Error %s rename %s -> "
4627 "%s\n", nt_errstr(status), directory,
4633 * If the src and dest names are identical - including case,
4634 * don't do the rename, just return success.
4637 if (strcsequal(directory, newname)) {
4638 DEBUG(3, ("rename_internals: identical names in "
4639 "rename %s - returning success\n",
4641 return NT_STATUS_OK;
4644 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4645 DEBUG(3,("rename_internals: dest exists doing "
4646 "rename %s -> %s\n", directory, newname));
4647 return NT_STATUS_OBJECT_NAME_COLLISION;
4650 if (rename_path_prefix_equal(directory, newname)) {
4651 return NT_STATUS_SHARING_VIOLATION;
4654 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4657 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4658 DEBUG(3,("rename_internals: succeeded doing rename "
4659 "on %s -> %s\n", directory, newname));
4660 rename_open_files(conn, lck, sbuf1.st_dev,
4661 sbuf1.st_ino, newname);
4663 notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4664 directory, newname);
4665 return NT_STATUS_OK;
4669 if (errno == ENOTDIR || errno == EISDIR) {
4670 status = NT_STATUS_OBJECT_NAME_COLLISION;
4672 status = map_nt_error_from_unix(errno);
4675 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4676 nt_errstr(status), directory,newname));
4682 * Wildcards - process each file that matches.
4684 if (strequal(mask,"????????.???")) {
4688 status = check_name(conn, directory);
4689 if (!NT_STATUS_IS_OK(status)) {
4693 dir_hnd = OpenDir(conn, directory, mask, attrs);
4694 if (dir_hnd == NULL) {
4695 return map_nt_error_from_unix(errno);
4698 status = NT_STATUS_NO_SUCH_FILE;
4700 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4701 * - gentest fix. JRA
4704 while ((dname = ReadDirName(dir_hnd, &offset))) {
4706 BOOL sysdir_entry = False;
4708 pstrcpy(fname,dname);
4710 /* Quick check for "." and ".." */
4711 if (fname[0] == '.') {
4712 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4714 sysdir_entry = True;
4721 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4725 if(!mask_match(fname, mask, conn->case_sensitive)) {
4730 status = NT_STATUS_OBJECT_NAME_INVALID;
4734 status = NT_STATUS_ACCESS_DENIED;
4735 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4737 /* Ensure the source name is valid for us to access. */
4738 status = check_name(conn, fname);
4739 if (!NT_STATUS_IS_OK(status)) {
4743 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4744 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4745 DEBUG(6, ("rename %s failed. Error %s\n",
4746 fname, nt_errstr(status)));
4749 status = can_rename(conn,fname,attrs,&sbuf1,False);
4750 if (!NT_STATUS_IS_OK(status)) {
4751 DEBUG(6, ("rename %s refused\n", fname));
4754 pstrcpy(destname,newname);
4756 if (!resolve_wildcards(fname,destname)) {
4757 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4762 /* Ensure the dest name is valid for us to access. */
4763 status = check_name(conn, destname);
4764 if (!NT_STATUS_IS_OK(status)) {
4768 if (strcsequal(fname,destname)) {
4769 DEBUG(3,("rename_internals: identical names "
4770 "in wildcard rename %s - success\n",
4773 status = NT_STATUS_OK;
4777 if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
4778 DEBUG(6,("file_exist %s\n", destname));
4779 status = NT_STATUS_OBJECT_NAME_COLLISION;
4783 if (rename_path_prefix_equal(fname, destname)) {
4784 return NT_STATUS_SHARING_VIOLATION;
4787 lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4788 sbuf1.st_ino, NULL, NULL);
4790 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4791 rename_open_files(conn, lck, sbuf1.st_dev,
4792 sbuf1.st_ino, newname);
4794 status = NT_STATUS_OK;
4797 DEBUG(3,("rename_internals: doing rename on %s -> "
4798 "%s\n",fname,destname));
4802 if (count == 0 && NT_STATUS_IS_OK(status)) {
4803 status = map_nt_error_from_unix(errno);
4809 /****************************************************************************
4811 ****************************************************************************/
4813 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4820 uint32 attrs = SVAL(inbuf,smb_vwv0);
4822 BOOL src_has_wcard = False;
4823 BOOL dest_has_wcard = False;
4825 START_PROFILE(SMBmv);
4827 p = smb_buf(inbuf) + 1;
4828 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
4829 if (!NT_STATUS_IS_OK(status)) {
4831 return ERROR_NT(status);
4834 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
4835 if (!NT_STATUS_IS_OK(status)) {
4837 return ERROR_NT(status);
4840 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4841 if (!NT_STATUS_IS_OK(status)) {
4843 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4844 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4846 return ERROR_NT(status);
4849 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4850 if (!NT_STATUS_IS_OK(status)) {
4852 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4853 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4855 return ERROR_NT(status);
4858 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4860 status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
4861 if (!NT_STATUS_IS_OK(status)) {
4863 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4864 /* We have re-scheduled this call. */
4867 return ERROR_NT(status);
4870 outsize = set_message(outbuf,0,0,False);
4876 /*******************************************************************
4877 Copy a file as part of a reply_copy.
4878 ******************************************************************/
4881 * TODO: check error codes on all callers
4884 NTSTATUS copy_file(connection_struct *conn,
4889 BOOL target_is_directory)
4891 SMB_STRUCT_STAT src_sbuf, sbuf2;
4893 files_struct *fsp1,*fsp2;
4896 uint32 new_create_disposition;
4899 pstrcpy(dest,dest1);
4900 if (target_is_directory) {
4901 char *p = strrchr_m(src,'/');
4911 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4912 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4915 if (!target_is_directory && count) {
4916 new_create_disposition = FILE_OPEN;
4918 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4919 NULL, NULL, &new_create_disposition, NULL)) {
4920 return NT_STATUS_INVALID_PARAMETER;
4924 status = open_file_ntcreate(conn,src,&src_sbuf,
4926 FILE_SHARE_READ|FILE_SHARE_WRITE,
4929 FILE_ATTRIBUTE_NORMAL,
4933 if (!NT_STATUS_IS_OK(status)) {
4937 dosattrs = dos_mode(conn, src, &src_sbuf);
4938 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4939 ZERO_STRUCTP(&sbuf2);
4942 status = open_file_ntcreate(conn,dest,&sbuf2,
4944 FILE_SHARE_READ|FILE_SHARE_WRITE,
4945 new_create_disposition,
4951 if (!NT_STATUS_IS_OK(status)) {
4952 close_file(fsp1,ERROR_CLOSE);
4956 if ((ofun&3) == 1) {
4957 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4958 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4960 * Stop the copy from occurring.
4963 src_sbuf.st_size = 0;
4967 if (src_sbuf.st_size) {
4968 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4971 close_file(fsp1,NORMAL_CLOSE);
4973 /* Ensure the modtime is set correctly on the destination file. */
4974 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4977 * As we are opening fsp1 read-only we only expect
4978 * an error on close on fsp2 if we are out of space.
4979 * Thus we don't look at the error return from the
4982 status = close_file(fsp2,NORMAL_CLOSE);
4984 if (!NT_STATUS_IS_OK(status)) {
4988 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4989 return NT_STATUS_DISK_FULL;
4992 return NT_STATUS_OK;
4995 /****************************************************************************
4996 Reply to a file copy.
4997 ****************************************************************************/
4999 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5004 pstring mask,newname;
5007 int error = ERRnoaccess;
5009 int tid2 = SVAL(inbuf,smb_vwv0);
5010 int ofun = SVAL(inbuf,smb_vwv1);
5011 int flags = SVAL(inbuf,smb_vwv2);
5012 BOOL target_is_directory=False;
5013 BOOL source_has_wild = False;
5014 BOOL dest_has_wild = False;
5015 SMB_STRUCT_STAT sbuf1, sbuf2;
5017 START_PROFILE(SMBcopy);
5019 *directory = *mask = 0;
5022 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 END_PROFILE(SMBcopy);
5025 return ERROR_NT(status);
5027 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
5028 if (!NT_STATUS_IS_OK(status)) {
5029 END_PROFILE(SMBcopy);
5030 return ERROR_NT(status);
5033 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5035 if (tid2 != conn->cnum) {
5036 /* can't currently handle inter share copies XXXX */
5037 DEBUG(3,("Rejecting inter-share copy\n"));
5038 END_PROFILE(SMBcopy);
5039 return ERROR_DOS(ERRSRV,ERRinvdevice);
5042 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5043 if (!NT_STATUS_IS_OK(status)) {
5044 END_PROFILE(SMBcopy);
5045 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5046 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5048 return ERROR_NT(status);
5051 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5052 if (!NT_STATUS_IS_OK(status)) {
5053 END_PROFILE(SMBcopy);
5054 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5055 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5057 return ERROR_NT(status);
5060 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5061 if (!NT_STATUS_IS_OK(status)) {
5062 END_PROFILE(SMBcopy);
5063 return ERROR_NT(status);
5066 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5067 if (!NT_STATUS_IS_OK(status)) {
5068 END_PROFILE(SMBcopy);
5069 return ERROR_NT(status);
5072 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5074 if ((flags&1) && target_is_directory) {
5075 END_PROFILE(SMBcopy);
5076 return ERROR_DOS(ERRDOS,ERRbadfile);
5079 if ((flags&2) && !target_is_directory) {
5080 END_PROFILE(SMBcopy);
5081 return ERROR_DOS(ERRDOS,ERRbadpath);
5084 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5085 /* wants a tree copy! XXXX */
5086 DEBUG(3,("Rejecting tree copy\n"));
5087 END_PROFILE(SMBcopy);
5088 return ERROR_DOS(ERRSRV,ERRerror);
5091 p = strrchr_m(name,'/');
5093 pstrcpy(directory,"./");
5097 pstrcpy(directory,name);
5102 * We should only check the mangled cache
5103 * here if unix_convert failed. This means
5104 * that the path in 'mask' doesn't exist
5105 * on the file system and so we need to look
5106 * for a possible mangle. This patch from
5107 * Tine Smukavec <valentin.smukavec@hermes.si>.
5110 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5111 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5114 if (!source_has_wild) {
5115 pstrcat(directory,"/");
5116 pstrcat(directory,mask);
5117 if (dest_has_wild) {
5118 if (!resolve_wildcards(directory,newname)) {
5119 END_PROFILE(SMBcopy);
5120 return ERROR_NT(NT_STATUS_NO_MEMORY);
5124 status = check_name(conn, directory);
5125 if (!NT_STATUS_IS_OK(status)) {
5126 return ERROR_NT(status);
5129 status = check_name(conn, newname);
5130 if (!NT_STATUS_IS_OK(status)) {
5131 return ERROR_NT(status);
5134 status = copy_file(conn,directory,newname,ofun,
5135 count,target_is_directory);
5137 if(!NT_STATUS_IS_OK(status)) {
5138 END_PROFILE(SMBcopy);
5139 return ERROR_NT(status);
5144 struct smb_Dir *dir_hnd = NULL;
5149 if (strequal(mask,"????????.???"))
5152 status = check_name(conn, directory);
5153 if (!NT_STATUS_IS_OK(status)) {
5154 return ERROR_NT(status);
5157 dir_hnd = OpenDir(conn, directory, mask, 0);
5158 if (dir_hnd == NULL) {
5159 status = map_nt_error_from_unix(errno);
5160 return ERROR_NT(status);
5165 while ((dname = ReadDirName(dir_hnd, &offset))) {
5167 pstrcpy(fname,dname);
5169 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5173 if(!mask_match(fname, mask, conn->case_sensitive)) {
5177 error = ERRnoaccess;
5178 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5179 pstrcpy(destname,newname);
5180 if (!resolve_wildcards(fname,destname)) {
5184 status = check_name(conn, fname);
5185 if (!NT_STATUS_IS_OK(status)) {
5186 return ERROR_NT(status);
5189 status = check_name(conn, destname);
5190 if (!NT_STATUS_IS_OK(status)) {
5191 return ERROR_NT(status);
5194 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5196 status = copy_file(conn,fname,destname,ofun,
5197 count,target_is_directory);
5198 if (NT_STATUS_IS_OK(status)) {
5207 /* Error on close... */
5209 END_PROFILE(SMBcopy);
5210 return(UNIXERROR(ERRHRD,ERRgeneral));
5213 END_PROFILE(SMBcopy);
5214 return ERROR_DOS(ERRDOS,error);
5217 outsize = set_message(outbuf,1,0,True);
5218 SSVAL(outbuf,smb_vwv0,count);
5220 END_PROFILE(SMBcopy);
5224 /****************************************************************************
5226 ****************************************************************************/
5228 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5235 START_PROFILE(pathworks_setdir);
5238 if (!CAN_SETDIR(snum)) {
5239 END_PROFILE(pathworks_setdir);
5240 return ERROR_DOS(ERRDOS,ERRnoaccess);
5243 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 END_PROFILE(pathworks_setdir);
5246 return ERROR_NT(status);
5249 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5250 if (!NT_STATUS_IS_OK(status)) {
5251 END_PROFILE(pathworks_setdir);
5252 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5253 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5255 return ERROR_NT(status);
5258 if (strlen(newdir) != 0) {
5259 if (!vfs_directory_exist(conn,newdir,NULL)) {
5260 END_PROFILE(pathworks_setdir);
5261 return ERROR_DOS(ERRDOS,ERRbadpath);
5263 set_conn_connectpath(conn,newdir);
5266 outsize = set_message(outbuf,0,0,False);
5267 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5269 DEBUG(3,("setdir %s\n", newdir));
5271 END_PROFILE(pathworks_setdir);
5276 #define DBGC_CLASS DBGC_LOCKING
5278 /****************************************************************************
5279 Get a lock pid, dealing with large count requests.
5280 ****************************************************************************/
5282 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5284 if(!large_file_format)
5285 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5287 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5290 /****************************************************************************
5291 Get a lock count, dealing with large count requests.
5292 ****************************************************************************/
5294 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5296 SMB_BIG_UINT count = 0;
5298 if(!large_file_format) {
5299 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5302 #if defined(HAVE_LONGLONG)
5303 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5304 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5305 #else /* HAVE_LONGLONG */
5308 * NT4.x seems to be broken in that it sends large file (64 bit)
5309 * lockingX calls even if the CAP_LARGE_FILES was *not*
5310 * negotiated. For boxes without large unsigned ints truncate the
5311 * lock count by dropping the top 32 bits.
5314 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5315 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5316 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5317 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5318 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5321 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5322 #endif /* HAVE_LONGLONG */
5328 #if !defined(HAVE_LONGLONG)
5329 /****************************************************************************
5330 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5331 ****************************************************************************/
5333 static uint32 map_lock_offset(uint32 high, uint32 low)
5337 uint32 highcopy = high;
5340 * Try and find out how many significant bits there are in high.
5343 for(i = 0; highcopy; i++)
5347 * We use 31 bits not 32 here as POSIX
5348 * lock offsets may not be negative.
5351 mask = (~0) << (31 - i);
5354 return 0; /* Fail. */
5360 #endif /* !defined(HAVE_LONGLONG) */
5362 /****************************************************************************
5363 Get a lock offset, dealing with large offset requests.
5364 ****************************************************************************/
5366 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5368 SMB_BIG_UINT offset = 0;
5372 if(!large_file_format) {
5373 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5376 #if defined(HAVE_LONGLONG)
5377 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5378 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5379 #else /* HAVE_LONGLONG */
5382 * NT4.x seems to be broken in that it sends large file (64 bit)
5383 * lockingX calls even if the CAP_LARGE_FILES was *not*
5384 * negotiated. For boxes without large unsigned ints mangle the
5385 * lock offset by mapping the top 32 bits onto the lower 32.
5388 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5389 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5390 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5393 if((new_low = map_lock_offset(high, low)) == 0) {
5395 return (SMB_BIG_UINT)-1;
5398 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5399 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5400 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5401 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5404 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5405 #endif /* HAVE_LONGLONG */
5411 /****************************************************************************
5412 Reply to a lockingX request.
5413 ****************************************************************************/
5415 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5416 int length, int bufsize)
5418 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5419 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5420 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5421 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5422 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5423 SMB_BIG_UINT count = 0, offset = 0;
5425 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5428 BOOL large_file_format =
5429 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5431 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5433 START_PROFILE(SMBlockingX);
5435 CHECK_FSP(fsp,conn);
5437 data = smb_buf(inbuf);
5439 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5440 /* we don't support these - and CANCEL_LOCK makes w2k
5441 and XP reboot so I don't really want to be
5442 compatible! (tridge) */
5443 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5446 /* Check if this is an oplock break on a file
5447 we have granted an oplock on.
5449 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5450 /* Client can insist on breaking to none. */
5451 BOOL break_to_none = (oplocklevel == 0);
5454 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5455 "for fnum = %d\n", (unsigned int)oplocklevel,
5459 * Make sure we have granted an exclusive or batch oplock on
5463 if (fsp->oplock_type == 0) {
5465 /* The Samba4 nbench simulator doesn't understand
5466 the difference between break to level2 and break
5467 to none from level2 - it sends oplock break
5468 replies in both cases. Don't keep logging an error
5469 message here - just ignore it. JRA. */
5471 DEBUG(5,("reply_lockingX: Error : oplock break from "
5472 "client for fnum = %d (oplock=%d) and no "
5473 "oplock granted on this file (%s).\n",
5474 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5476 /* if this is a pure oplock break request then don't
5478 if (num_locks == 0 && num_ulocks == 0) {
5479 END_PROFILE(SMBlockingX);
5482 END_PROFILE(SMBlockingX);
5483 return ERROR_DOS(ERRDOS,ERRlock);
5487 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5489 result = remove_oplock(fsp);
5491 result = downgrade_oplock(fsp);
5495 DEBUG(0, ("reply_lockingX: error in removing "
5496 "oplock on file %s\n", fsp->fsp_name));
5497 /* Hmmm. Is this panic justified? */
5498 smb_panic("internal tdb error");
5501 reply_to_oplock_break_requests(fsp);
5503 /* if this is a pure oplock break request then don't send a
5505 if (num_locks == 0 && num_ulocks == 0) {
5506 /* Sanity check - ensure a pure oplock break is not a
5508 if(CVAL(inbuf,smb_vwv0) != 0xff)
5509 DEBUG(0,("reply_lockingX: Error : pure oplock "
5510 "break is a chained %d request !\n",
5511 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5512 END_PROFILE(SMBlockingX);
5518 * We do this check *after* we have checked this is not a oplock break
5519 * response message. JRA.
5522 release_level_2_oplocks_on_change(fsp);
5524 /* Data now points at the beginning of the list
5525 of smb_unlkrng structs */
5526 for(i = 0; i < (int)num_ulocks; i++) {
5527 lock_pid = get_lock_pid( data, i, large_file_format);
5528 count = get_lock_count( data, i, large_file_format);
5529 offset = get_lock_offset( data, i, large_file_format, &err);
5532 * There is no error code marked "stupid client bug".... :-).
5535 END_PROFILE(SMBlockingX);
5536 return ERROR_DOS(ERRDOS,ERRnoaccess);
5539 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5540 "pid %u, file %s\n", (double)offset, (double)count,
5541 (unsigned int)lock_pid, fsp->fsp_name ));
5543 status = do_unlock(fsp,
5549 if (NT_STATUS_V(status)) {
5550 END_PROFILE(SMBlockingX);
5551 return ERROR_NT(status);
5555 /* Setup the timeout in seconds. */
5557 if (!lp_blocking_locks(SNUM(conn))) {
5561 /* Now do any requested locks */
5562 data += ((large_file_format ? 20 : 10)*num_ulocks);
5564 /* Data now points at the beginning of the list
5565 of smb_lkrng structs */
5567 for(i = 0; i < (int)num_locks; i++) {
5568 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5569 READ_LOCK:WRITE_LOCK);
5570 lock_pid = get_lock_pid( data, i, large_file_format);
5571 count = get_lock_count( data, i, large_file_format);
5572 offset = get_lock_offset( data, i, large_file_format, &err);
5575 * There is no error code marked "stupid client bug".... :-).
5578 END_PROFILE(SMBlockingX);
5579 return ERROR_DOS(ERRDOS,ERRnoaccess);
5582 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5583 "%u, file %s timeout = %d\n", (double)offset,
5584 (double)count, (unsigned int)lock_pid,
5585 fsp->fsp_name, (int)lock_timeout ));
5587 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5588 if (lp_blocking_locks(SNUM(conn))) {
5590 /* Schedule a message to ourselves to
5591 remove the blocking lock record and
5592 return the right error. */
5594 if (!blocking_lock_cancel(fsp,
5600 NT_STATUS_FILE_LOCK_CONFLICT)) {
5601 END_PROFILE(SMBlockingX);
5602 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5605 /* Remove a matching pending lock. */
5606 status = do_lock_cancel(fsp,
5612 BOOL blocking_lock = lock_timeout ? True : False;
5613 BOOL defer_lock = False;
5614 struct byte_range_lock *br_lck;
5615 uint32 block_smbpid;
5617 br_lck = do_lock(fsp,
5627 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5628 /* Windows internal resolution for blocking locks seems
5629 to be about 200ms... Don't wait for less than that. JRA. */
5630 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5631 lock_timeout = lp_lock_spin_time();
5636 /* This heuristic seems to match W2K3 very well. If a
5637 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5638 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5639 far as I can tell. Replacement for do_lock_spin(). JRA. */
5641 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5642 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5644 lock_timeout = lp_lock_spin_time();
5647 if (br_lck && defer_lock) {
5649 * A blocking lock was requested. Package up
5650 * this smb into a queued request and push it
5651 * onto the blocking lock queue.
5653 if(push_blocking_lock_request(br_lck,
5664 TALLOC_FREE(br_lck);
5665 END_PROFILE(SMBlockingX);
5670 TALLOC_FREE(br_lck);
5673 if (NT_STATUS_V(status)) {
5674 END_PROFILE(SMBlockingX);
5675 return ERROR_NT(status);
5679 /* If any of the above locks failed, then we must unlock
5680 all of the previous locks (X/Open spec). */
5682 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5686 * Ensure we don't do a remove on the lock that just failed,
5687 * as under POSIX rules, if we have a lock already there, we
5688 * will delete it (and we shouldn't) .....
5690 for(i--; i >= 0; i--) {
5691 lock_pid = get_lock_pid( data, i, large_file_format);
5692 count = get_lock_count( data, i, large_file_format);
5693 offset = get_lock_offset( data, i, large_file_format,
5697 * There is no error code marked "stupid client
5701 END_PROFILE(SMBlockingX);
5702 return ERROR_DOS(ERRDOS,ERRnoaccess);
5711 END_PROFILE(SMBlockingX);
5712 return ERROR_NT(status);
5715 set_message(outbuf,2,0,True);
5717 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5718 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5720 END_PROFILE(SMBlockingX);
5721 return chain_reply(inbuf,outbuf,length,bufsize);
5725 #define DBGC_CLASS DBGC_ALL
5727 /****************************************************************************
5728 Reply to a SMBreadbmpx (read block multiplex) request.
5729 ****************************************************************************/
5731 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5742 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5743 START_PROFILE(SMBreadBmpx);
5745 /* this function doesn't seem to work - disable by default */
5746 if (!lp_readbmpx()) {
5747 END_PROFILE(SMBreadBmpx);
5748 return ERROR_DOS(ERRSRV,ERRuseSTD);
5751 outsize = set_message(outbuf,8,0,True);
5753 CHECK_FSP(fsp,conn);
5754 if (!CHECK_READ(fsp,inbuf)) {
5755 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5758 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5759 maxcount = SVAL(inbuf,smb_vwv3);
5761 data = smb_buf(outbuf);
5762 pad = ((long)data)%4;
5767 max_per_packet = bufsize-(outsize+pad);
5771 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5772 END_PROFILE(SMBreadBmpx);
5773 return ERROR_DOS(ERRDOS,ERRlock);
5777 size_t N = MIN(max_per_packet,tcount-total_read);
5779 nread = read_file(fsp,data,startpos,N);
5784 if (nread < (ssize_t)N)
5785 tcount = total_read + nread;
5787 set_message(outbuf,8,nread+pad,False);
5788 SIVAL(outbuf,smb_vwv0,startpos);
5789 SSVAL(outbuf,smb_vwv2,tcount);
5790 SSVAL(outbuf,smb_vwv6,nread);
5791 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5794 if (!send_smb(smbd_server_fd(),outbuf))
5795 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5797 total_read += nread;
5799 } while (total_read < (ssize_t)tcount);
5801 END_PROFILE(SMBreadBmpx);
5805 /****************************************************************************
5806 Reply to a SMBsetattrE.
5807 ****************************************************************************/
5809 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5811 struct timespec ts[2];
5813 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5814 START_PROFILE(SMBsetattrE);
5816 outsize = set_message(outbuf,0,0,False);
5818 if(!fsp || (fsp->conn != conn)) {
5819 END_PROFILE(SMBsetattrE);
5820 return ERROR_DOS(ERRDOS,ERRbadfid);
5824 * Convert the DOS times into unix times. Ignore create
5825 * time as UNIX can't set this.
5828 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5829 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5832 * Patch from Ray Frush <frush@engr.colostate.edu>
5833 * Sometimes times are sent as zero - ignore them.
5836 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5837 /* Ignore request */
5838 if( DEBUGLVL( 3 ) ) {
5839 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5840 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5842 END_PROFILE(SMBsetattrE);
5844 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5845 /* set modify time = to access time if modify time was unset */
5849 /* Set the date on this file */
5850 /* Should we set pending modtime here ? JRA */
5851 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5852 END_PROFILE(SMBsetattrE);
5853 return ERROR_DOS(ERRDOS,ERRnoaccess);
5856 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5858 (unsigned int)ts[0].tv_sec,
5859 (unsigned int)ts[1].tv_sec));
5861 END_PROFILE(SMBsetattrE);
5866 /* Back from the dead for OS/2..... JRA. */
5868 /****************************************************************************
5869 Reply to a SMBwritebmpx (write block multiplex primary) request.
5870 ****************************************************************************/
5872 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5875 ssize_t nwritten = -1;
5882 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5884 START_PROFILE(SMBwriteBmpx);
5886 CHECK_FSP(fsp,conn);
5887 if (!CHECK_WRITE(fsp)) {
5888 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5890 if (HAS_CACHED_ERROR(fsp)) {
5891 return(CACHED_ERROR(fsp));
5894 tcount = SVAL(inbuf,smb_vwv1);
5895 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5896 write_through = BITSETW(inbuf+smb_vwv7,0);
5897 numtowrite = SVAL(inbuf,smb_vwv10);
5898 smb_doff = SVAL(inbuf,smb_vwv11);
5900 data = smb_base(inbuf) + smb_doff;
5902 /* If this fails we need to send an SMBwriteC response,
5903 not an SMBwritebmpx - set this up now so we don't forget */
5904 SCVAL(outbuf,smb_com,SMBwritec);
5906 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5907 END_PROFILE(SMBwriteBmpx);
5908 return(ERROR_DOS(ERRDOS,ERRlock));
5911 nwritten = write_file(fsp,data,startpos,numtowrite);
5913 status = sync_file(conn, fsp, write_through);
5914 if (!NT_STATUS_IS_OK(status)) {
5915 END_PROFILE(SMBwriteBmpx);
5916 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
5917 fsp->fsp_name, nt_errstr(status) ));
5918 return ERROR_NT(status);
5921 if(nwritten < (ssize_t)numtowrite) {
5922 END_PROFILE(SMBwriteBmpx);
5923 return(UNIXERROR(ERRHRD,ERRdiskfull));
5926 /* If the maximum to be written to this file
5927 is greater than what we just wrote then set
5928 up a secondary struct to be attached to this
5929 fd, we will use this to cache error messages etc. */
5931 if((ssize_t)tcount > nwritten) {
5932 write_bmpx_struct *wbms;
5933 if(fsp->wbmpx_ptr != NULL)
5934 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5936 wbms = SMB_MALLOC_P(write_bmpx_struct);
5938 DEBUG(0,("Out of memory in reply_readmpx\n"));
5939 END_PROFILE(SMBwriteBmpx);
5940 return(ERROR_DOS(ERRSRV,ERRnoresource));
5942 wbms->wr_mode = write_through;
5943 wbms->wr_discard = False; /* No errors yet */
5944 wbms->wr_total_written = nwritten;
5945 wbms->wr_errclass = 0;
5947 fsp->wbmpx_ptr = wbms;
5950 /* We are returning successfully, set the message type back to
5952 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5954 outsize = set_message(outbuf,1,0,True);
5956 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5958 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5959 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5961 if (write_through && tcount==nwritten) {
5962 /* We need to send both a primary and a secondary response */
5963 smb_setlen(outbuf,outsize - 4);
5965 if (!send_smb(smbd_server_fd(),outbuf))
5966 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5968 /* Now the secondary */
5969 outsize = set_message(outbuf,1,0,True);
5970 SCVAL(outbuf,smb_com,SMBwritec);
5971 SSVAL(outbuf,smb_vwv0,nwritten);
5974 END_PROFILE(SMBwriteBmpx);
5978 /****************************************************************************
5979 Reply to a SMBwritebs (write block multiplex secondary) request.
5980 ****************************************************************************/
5982 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5985 ssize_t nwritten = -1;
5992 write_bmpx_struct *wbms;
5993 BOOL send_response = False;
5994 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5996 START_PROFILE(SMBwriteBs);
5998 CHECK_FSP(fsp,conn);
5999 if (!CHECK_WRITE(fsp)) {
6000 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6003 tcount = SVAL(inbuf,smb_vwv1);
6004 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6005 numtowrite = SVAL(inbuf,smb_vwv6);
6006 smb_doff = SVAL(inbuf,smb_vwv7);
6008 data = smb_base(inbuf) + smb_doff;
6010 /* We need to send an SMBwriteC response, not an SMBwritebs */
6011 SCVAL(outbuf,smb_com,SMBwritec);
6013 /* This fd should have an auxiliary struct attached,
6014 check that it does */
6015 wbms = fsp->wbmpx_ptr;
6017 END_PROFILE(SMBwriteBs);
6021 /* If write through is set we can return errors, else we must cache them */
6022 write_through = wbms->wr_mode;
6024 /* Check for an earlier error */
6025 if(wbms->wr_discard) {
6026 END_PROFILE(SMBwriteBs);
6027 return -1; /* Just discard the packet */
6030 nwritten = write_file(fsp,data,startpos,numtowrite);
6032 status = sync_file(conn, fsp, write_through);
6034 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6036 /* We are returning an error - we can delete the aux struct */
6039 fsp->wbmpx_ptr = NULL;
6040 END_PROFILE(SMBwriteBs);
6041 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6043 wbms->wr_errclass = ERRHRD;
6044 wbms->wr_error = ERRdiskfull;
6045 wbms->wr_status = NT_STATUS_DISK_FULL;
6046 wbms->wr_discard = True;
6047 END_PROFILE(SMBwriteBs);
6051 /* Increment the total written, if this matches tcount
6052 we can discard the auxiliary struct (hurrah !) and return a writeC */
6053 wbms->wr_total_written += nwritten;
6054 if(wbms->wr_total_written >= tcount) {
6055 if (write_through) {
6056 outsize = set_message(outbuf,1,0,True);
6057 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6058 send_response = True;
6062 fsp->wbmpx_ptr = NULL;
6066 END_PROFILE(SMBwriteBs);
6070 END_PROFILE(SMBwriteBs);
6074 /****************************************************************************
6075 Reply to a SMBgetattrE.
6076 ****************************************************************************/
6078 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6080 SMB_STRUCT_STAT sbuf;
6083 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6084 START_PROFILE(SMBgetattrE);
6086 outsize = set_message(outbuf,11,0,True);
6088 if(!fsp || (fsp->conn != conn)) {
6089 END_PROFILE(SMBgetattrE);
6090 return ERROR_DOS(ERRDOS,ERRbadfid);
6093 /* Do an fstat on this file */
6094 if(fsp_stat(fsp, &sbuf)) {
6095 END_PROFILE(SMBgetattrE);
6096 return(UNIXERROR(ERRDOS,ERRnoaccess));
6099 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6102 * Convert the times into dos times. Set create
6103 * date to be last modify date as UNIX doesn't save
6107 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6108 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6109 /* Should we check pending modtime here ? JRA */
6110 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6113 SIVAL(outbuf,smb_vwv6,0);
6114 SIVAL(outbuf,smb_vwv8,0);
6116 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6117 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6118 SIVAL(outbuf,smb_vwv8,allocation_size);
6120 SSVAL(outbuf,smb_vwv10, mode);
6122 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6124 END_PROFILE(SMBgetattrE);