2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
33 unsigned int smb_echo_count = 0;
34 extern uint32 global_client_caps;
36 extern struct current_user current_user;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41 path or anything including wildcards.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 NTSTATUS check_path_syntax_internal(pstring destname,
48 const pstring srcname,
50 BOOL *p_last_component_contains_wcard)
53 const char *s = srcname;
54 NTSTATUS ret = NT_STATUS_OK;
55 BOOL start_of_name_component = True;
57 *p_last_component_contains_wcard = False;
60 if (IS_DIRECTORY_SEP(*s)) {
62 * Safe to assume is not the second part of a mb char
63 * as this is handled below.
65 /* Eat multiple '/' or '\\' */
66 while (IS_DIRECTORY_SEP(*s)) {
69 if ((d != destname) && (*s != '\0')) {
70 /* We only care about non-leading or trailing '/' or '\\' */
74 start_of_name_component = True;
76 *p_last_component_contains_wcard = False;
80 if (start_of_name_component) {
81 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
82 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
85 * No mb char starts with '.' so we're safe checking the directory separator here.
88 /* If we just added a '/' - delete it */
89 if ((d > destname) && (*(d-1) == '/')) {
94 /* Are we at the start ? Can't go back further if so. */
96 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
99 /* Go back one level... */
100 /* We know this is safe as '/' cannot be part of a mb sequence. */
101 /* NOTE - if this assumption is invalid we are not in good shape... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d--; d > destname; d--) {
107 s += 2; /* Else go past the .. */
108 /* We're still at the start of a name component, just the previous one. */
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
124 return NT_STATUS_OBJECT_NAME_INVALID;
132 *p_last_component_contains_wcard = True;
141 /* Get the size of the next MB character. */
142 next_codepoint(s,&siz);
160 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162 return NT_STATUS_INVALID_PARAMETER;
165 start_of_name_component = False;
172 /****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175 ****************************************************************************/
177 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
180 return check_path_syntax_internal(destname, srcname, True, &ignore);
183 /****************************************************************************
184 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
185 Wildcards allowed - p_contains_wcard returns true if the last component contained
187 ****************************************************************************/
189 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
191 return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
194 /****************************************************************************
195 Check the path for a POSIX client.
196 We're assuming here that '/' is not the second byte in any multibyte char
197 set (a safe assumption).
198 ****************************************************************************/
200 static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
203 return check_path_syntax_internal(destname, srcname, False, &ignore);
206 /****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208 ****************************************************************************/
210 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
211 NTSTATUS *err, BOOL *contains_wcard)
214 char *tmppath_ptr = tmppath;
217 SMB_ASSERT(dest_len == sizeof(pstring));
221 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
223 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
226 *contains_wcard = False;
228 if (lp_posix_pathnames()) {
229 *err = check_path_syntax_posix(dest, tmppath);
231 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
237 /****************************************************************************
238 Pull a string and check the path - provide for error return.
239 ****************************************************************************/
241 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
244 char *tmppath_ptr = tmppath;
247 SMB_ASSERT(dest_len == sizeof(pstring));
251 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
253 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
255 if (lp_posix_pathnames()) {
256 *err = check_path_syntax_posix(dest, tmppath);
258 *err = check_path_syntax(dest, tmppath);
264 /****************************************************************************
265 Reply to a special message.
266 ****************************************************************************/
268 int reply_special(char *inbuf,char *outbuf)
271 int msg_type = CVAL(inbuf,0);
272 int msg_flags = CVAL(inbuf,1);
276 static BOOL already_got_session = False;
280 memset(outbuf,'\0',smb_size);
282 smb_setlen(outbuf,0);
285 case 0x81: /* session request */
287 if (already_got_session) {
288 exit_server_cleanly("multiple session request not permitted");
291 SCVAL(outbuf,0,0x82);
293 if (name_len(inbuf+4) > 50 ||
294 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
295 DEBUG(0,("Invalid name length in session request\n"));
298 name_extract(inbuf,4,name1);
299 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
300 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
303 set_local_machine_name(name1, True);
304 set_remote_machine_name(name2, True);
306 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
307 get_local_machine_name(), get_remote_machine_name(),
310 if (name_type == 'R') {
311 /* We are being asked for a pathworks session ---
313 SCVAL(outbuf, 0,0x83);
317 /* only add the client's machine name to the list
318 of possibly valid usernames if we are operating
319 in share mode security */
320 if (lp_security() == SEC_SHARE) {
321 add_session_user(get_remote_machine_name());
324 reload_services(True);
327 already_got_session = True;
330 case 0x89: /* session keepalive request
331 (some old clients produce this?) */
332 SCVAL(outbuf,0,SMBkeepalive);
336 case 0x82: /* positive session response */
337 case 0x83: /* negative session response */
338 case 0x84: /* retarget session response */
339 DEBUG(0,("Unexpected session response\n"));
342 case SMBkeepalive: /* session keepalive */
347 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
348 msg_type, msg_flags));
353 /****************************************************************************
355 conn POINTER CAN BE NULL HERE !
356 ****************************************************************************/
358 int reply_tcon(connection_struct *conn,
359 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
366 uint16 vuid = SVAL(inbuf,smb_uid);
370 DATA_BLOB password_blob;
372 START_PROFILE(SMBtcon);
374 *service_buf = *password = *dev = 0;
376 p = smb_buf(inbuf)+1;
377 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
378 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
380 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
382 p = strrchr_m(service_buf,'\\');
386 service = service_buf;
389 password_blob = data_blob(password, pwlen+1);
391 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
393 data_blob_clear_free(&password_blob);
396 END_PROFILE(SMBtcon);
397 return ERROR_NT(nt_status);
400 outsize = set_message(outbuf,2,0,True);
401 SSVAL(outbuf,smb_vwv0,max_recv);
402 SSVAL(outbuf,smb_vwv1,conn->cnum);
403 SSVAL(outbuf,smb_tid,conn->cnum);
405 DEBUG(3,("tcon service=%s cnum=%d\n",
406 service, conn->cnum));
408 END_PROFILE(SMBtcon);
412 /****************************************************************************
413 Reply to a tcon and X.
414 conn POINTER CAN BE NULL HERE !
415 ****************************************************************************/
417 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
422 /* what the cleint thinks the device is */
423 fstring client_devicetype;
424 /* what the server tells the client the share represents */
425 const char *server_devicetype;
427 uint16 vuid = SVAL(inbuf,smb_uid);
428 int passlen = SVAL(inbuf,smb_vwv3);
432 START_PROFILE(SMBtconX);
434 *service = *client_devicetype = 0;
436 /* we might have to close an old one */
437 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
438 close_cnum(conn,vuid);
441 if (passlen > MAX_PASS_LEN) {
442 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
445 if (global_encrypted_passwords_negotiated) {
446 password = data_blob(smb_buf(inbuf),passlen);
448 password = data_blob(smb_buf(inbuf),passlen+1);
449 /* Ensure correct termination */
450 password.data[passlen]=0;
453 p = smb_buf(inbuf) + passlen;
454 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
457 * the service name can be either: \\server\share
458 * or share directly like on the DELL PowerVault 705
461 q = strchr_m(path+2,'\\');
463 END_PROFILE(SMBtconX);
464 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
466 fstrcpy(service,q+1);
469 fstrcpy(service,path);
471 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
473 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
475 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
477 data_blob_clear_free(&password);
480 END_PROFILE(SMBtconX);
481 return ERROR_NT(nt_status);
485 server_devicetype = "IPC";
486 else if ( IS_PRINT(conn) )
487 server_devicetype = "LPT1:";
489 server_devicetype = "A:";
491 if (Protocol < PROTOCOL_NT1) {
492 set_message(outbuf,2,0,True);
494 p += srvstr_push(outbuf, p, server_devicetype, -1,
495 STR_TERMINATE|STR_ASCII);
496 set_message_end(outbuf,p);
498 /* NT sets the fstype of IPC$ to the null string */
499 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
501 set_message(outbuf,3,0,True);
504 p += srvstr_push(outbuf, p, server_devicetype, -1,
505 STR_TERMINATE|STR_ASCII);
506 p += srvstr_push(outbuf, p, fstype, -1,
509 set_message_end(outbuf,p);
511 /* what does setting this bit do? It is set by NT4 and
512 may affect the ability to autorun mounted cdroms */
513 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
514 (lp_csc_policy(SNUM(conn)) << 2));
516 init_dfsroot(conn, inbuf, outbuf);
520 DEBUG(3,("tconX service=%s \n",
523 /* set the incoming and outgoing tid to the just created one */
524 SSVAL(inbuf,smb_tid,conn->cnum);
525 SSVAL(outbuf,smb_tid,conn->cnum);
527 END_PROFILE(SMBtconX);
528 return chain_reply(inbuf,outbuf,length,bufsize);
531 /****************************************************************************
532 Reply to an unknown type.
533 ****************************************************************************/
535 int reply_unknown(char *inbuf,char *outbuf)
538 type = CVAL(inbuf,smb_com);
540 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
541 smb_fn_name(type), type, type));
543 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
546 /****************************************************************************
548 conn POINTER CAN BE NULL HERE !
549 ****************************************************************************/
551 int reply_ioctl(connection_struct *conn,
552 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
554 uint16 device = SVAL(inbuf,smb_vwv1);
555 uint16 function = SVAL(inbuf,smb_vwv2);
556 uint32 ioctl_code = (device << 16) + function;
557 int replysize, outsize;
559 START_PROFILE(SMBioctl);
561 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
563 switch (ioctl_code) {
564 case IOCTL_QUERY_JOB_INFO:
568 END_PROFILE(SMBioctl);
569 return(ERROR_DOS(ERRSRV,ERRnosupport));
572 outsize = set_message(outbuf,8,replysize+1,True);
573 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
574 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
575 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
576 p = smb_buf(outbuf) + 1; /* Allow for alignment */
578 switch (ioctl_code) {
579 case IOCTL_QUERY_JOB_INFO:
581 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
583 END_PROFILE(SMBioctl);
584 return(UNIXERROR(ERRDOS,ERRbadfid));
586 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
587 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
589 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
595 END_PROFILE(SMBioctl);
599 /****************************************************************************
600 Strange checkpath NTSTATUS mapping.
601 ****************************************************************************/
603 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
605 /* Strange DOS error code semantics only for checkpath... */
606 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
607 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
608 /* We need to map to ERRbadpath */
609 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
615 /****************************************************************************
616 Reply to a checkpath.
617 ****************************************************************************/
619 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
623 SMB_STRUCT_STAT sbuf;
626 START_PROFILE(SMBcheckpath);
628 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
629 if (!NT_STATUS_IS_OK(status)) {
630 END_PROFILE(SMBcheckpath);
631 status = map_checkpath_error(inbuf, status);
632 return ERROR_NT(status);
635 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
636 END_PROFILE(SMBcheckpath);
637 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
640 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
642 status = unix_convert(conn, name, False, NULL, &sbuf);
643 if (!NT_STATUS_IS_OK(status)) {
647 status = check_name(conn, name);
648 if (!NT_STATUS_IS_OK(status)) {
649 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
653 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
654 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
655 status = map_nt_error_from_unix(errno);
659 if (!S_ISDIR(sbuf.st_mode)) {
660 END_PROFILE(SMBcheckpath);
661 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
664 outsize = set_message(outbuf,0,0,False);
666 END_PROFILE(SMBcheckpath);
671 END_PROFILE(SMBcheckpath);
673 /* We special case this - as when a Windows machine
674 is parsing a path is steps through the components
675 one at a time - if a component fails it expects
676 ERRbadpath, not ERRbadfile.
678 status = map_checkpath_error(inbuf, status);
679 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
681 * Windows returns different error codes if
682 * the parent directory is valid but not the
683 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
684 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
685 * if the path is invalid.
687 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
690 return ERROR_NT(status);
693 /****************************************************************************
695 ****************************************************************************/
697 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
701 SMB_STRUCT_STAT sbuf;
708 START_PROFILE(SMBgetatr);
710 p = smb_buf(inbuf) + 1;
711 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
712 if (!NT_STATUS_IS_OK(status)) {
713 END_PROFILE(SMBgetatr);
714 return ERROR_NT(status);
717 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
718 END_PROFILE(SMBgetatr);
719 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
722 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
723 under WfWg - weird! */
724 if (*fname == '\0') {
725 mode = aHIDDEN | aDIR;
726 if (!CAN_WRITE(conn)) {
732 status = unix_convert(conn, fname, False, NULL,&sbuf);
733 if (!NT_STATUS_IS_OK(status)) {
734 END_PROFILE(SMBgetatr);
735 return ERROR_NT(status);
737 status = check_name(conn, fname);
738 if (!NT_STATUS_IS_OK(status)) {
739 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
740 END_PROFILE(SMBgetatr);
741 return ERROR_NT(status);
743 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
744 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
745 return UNIXERROR(ERRDOS,ERRbadfile);
748 mode = dos_mode(conn,fname,&sbuf);
750 mtime = sbuf.st_mtime;
756 outsize = set_message(outbuf,10,0,True);
758 SSVAL(outbuf,smb_vwv0,mode);
759 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
760 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
762 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
764 SIVAL(outbuf,smb_vwv3,(uint32)size);
766 if (Protocol >= PROTOCOL_NT1) {
767 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
770 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
772 END_PROFILE(SMBgetatr);
776 /****************************************************************************
778 ****************************************************************************/
780 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
786 SMB_STRUCT_STAT sbuf;
790 START_PROFILE(SMBsetatr);
792 p = smb_buf(inbuf) + 1;
793 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
794 if (!NT_STATUS_IS_OK(status)) {
795 END_PROFILE(SMBsetatr);
796 return ERROR_NT(status);
799 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
800 END_PROFILE(SMBsetatr);
801 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
804 status = unix_convert(conn, fname, False, NULL, &sbuf);
805 if (!NT_STATUS_IS_OK(status)) {
806 END_PROFILE(SMBsetatr);
807 return ERROR_NT(status);
810 status = check_name(conn, fname);
811 if (!NT_STATUS_IS_OK(status)) {
812 END_PROFILE(SMBsetatr);
813 return ERROR_NT(status);
816 if (fname[0] == '.' && fname[1] == '\0') {
818 * Not sure here is the right place to catch this
819 * condition. Might be moved to somewhere else later -- vl
821 END_PROFILE(SMBsetatr);
822 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
825 mode = SVAL(inbuf,smb_vwv0);
826 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
828 if (mode != FILE_ATTRIBUTE_NORMAL) {
829 if (VALID_STAT_OF_DIR(sbuf))
834 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
835 END_PROFILE(SMBsetatr);
836 return UNIXERROR(ERRDOS, ERRnoaccess);
840 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
841 END_PROFILE(SMBsetatr);
842 return UNIXERROR(ERRDOS, ERRnoaccess);
845 outsize = set_message(outbuf,0,0,False);
847 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
849 END_PROFILE(SMBsetatr);
853 /****************************************************************************
855 ****************************************************************************/
857 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
860 SMB_BIG_UINT dfree,dsize,bsize;
861 START_PROFILE(SMBdskattr);
863 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
864 END_PROFILE(SMBdskattr);
865 return(UNIXERROR(ERRHRD,ERRgeneral));
868 outsize = set_message(outbuf,5,0,True);
870 if (Protocol <= PROTOCOL_LANMAN2) {
871 double total_space, free_space;
872 /* we need to scale this to a number that DOS6 can handle. We
873 use floating point so we can handle large drives on systems
874 that don't have 64 bit integers
876 we end up displaying a maximum of 2G to DOS systems
878 total_space = dsize * (double)bsize;
879 free_space = dfree * (double)bsize;
881 dsize = (total_space+63*512) / (64*512);
882 dfree = (free_space+63*512) / (64*512);
884 if (dsize > 0xFFFF) dsize = 0xFFFF;
885 if (dfree > 0xFFFF) dfree = 0xFFFF;
887 SSVAL(outbuf,smb_vwv0,dsize);
888 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
889 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
890 SSVAL(outbuf,smb_vwv3,dfree);
892 SSVAL(outbuf,smb_vwv0,dsize);
893 SSVAL(outbuf,smb_vwv1,bsize/512);
894 SSVAL(outbuf,smb_vwv2,512);
895 SSVAL(outbuf,smb_vwv3,dfree);
898 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
900 END_PROFILE(SMBdskattr);
904 /****************************************************************************
906 Can be called from SMBsearch, SMBffirst or SMBfunique.
907 ****************************************************************************/
909 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
919 unsigned int numentries = 0;
920 unsigned int maxentries = 0;
921 BOOL finished = False;
927 BOOL check_descend = False;
928 BOOL expect_close = False;
930 BOOL mask_contains_wcard = False;
931 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
933 START_PROFILE(SMBsearch);
935 if (lp_posix_pathnames()) {
936 END_PROFILE(SMBsearch);
937 return reply_unknown(inbuf, outbuf);
940 *mask = *directory = *fname = 0;
942 /* If we were called as SMBffirst then we must expect close. */
943 if(CVAL(inbuf,smb_com) == SMBffirst) {
947 outsize = set_message(outbuf,1,3,True);
948 maxentries = SVAL(inbuf,smb_vwv0);
949 dirtype = SVAL(inbuf,smb_vwv1);
950 p = smb_buf(inbuf) + 1;
951 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
952 if (!NT_STATUS_IS_OK(nt_status)) {
953 END_PROFILE(SMBsearch);
954 return ERROR_NT(nt_status);
957 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path)) {
958 END_PROFILE(SMBsearch);
959 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
963 status_len = SVAL(p, 0);
966 /* dirtype &= ~aDIR; */
968 if (status_len == 0) {
969 SMB_STRUCT_STAT sbuf;
971 pstrcpy(directory,path);
972 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
973 if (!NT_STATUS_IS_OK(nt_status)) {
974 END_PROFILE(SMBsearch);
975 return ERROR_NT(nt_status);
978 nt_status = check_name(conn, directory);
979 if (!NT_STATUS_IS_OK(nt_status)) {
980 END_PROFILE(SMBsearch);
981 return ERROR_NT(nt_status);
984 p = strrchr_m(directory,'/');
986 pstrcpy(mask,directory);
987 pstrcpy(directory,".");
993 if (*directory == '\0') {
994 pstrcpy(directory,".");
996 memset((char *)status,'\0',21);
997 SCVAL(status,0,(dirtype & 0x1F));
1001 memcpy(status,p,21);
1002 status_dirtype = CVAL(status,0) & 0x1F;
1003 if (status_dirtype != (dirtype & 0x1F)) {
1004 dirtype = status_dirtype;
1007 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1008 if (!conn->dirptr) {
1011 string_set(&conn->dirpath,dptr_path(dptr_num));
1012 pstrcpy(mask, dptr_wcard(dptr_num));
1014 * For a 'continue' search we have no string. So
1015 * check from the initial saved string.
1017 mask_contains_wcard = ms_has_wild(mask);
1020 p = smb_buf(outbuf) + 3;
1022 if (status_len == 0) {
1023 nt_status = dptr_create(conn,
1027 SVAL(inbuf,smb_pid),
1029 mask_contains_wcard,
1032 if (!NT_STATUS_IS_OK(nt_status)) {
1033 return ERROR_NT(nt_status);
1035 dptr_num = dptr_dnum(conn->dirptr);
1037 dirtype = dptr_attr(dptr_num);
1040 DEBUG(4,("dptr_num is %d\n",dptr_num));
1042 if ((dirtype&0x1F) == aVOLID) {
1043 memcpy(p,status,21);
1044 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1045 0,aVOLID,0,!allow_long_path_components);
1046 dptr_fill(p+12,dptr_num);
1047 if (dptr_zero(p+12) && (status_len==0)) {
1052 p += DIR_STRUCT_SIZE;
1055 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1057 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1058 conn->dirpath,lp_dontdescend(SNUM(conn))));
1059 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1060 check_descend = True;
1063 for (i=numentries;(i<maxentries) && !finished;i++) {
1064 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1066 memcpy(p,status,21);
1067 make_dir_struct(p,mask,fname,size, mode,date,
1068 !allow_long_path_components);
1069 if (!dptr_fill(p+12,dptr_num)) {
1073 p += DIR_STRUCT_SIZE;
1080 /* If we were called as SMBffirst with smb_search_id == NULL
1081 and no entries were found then return error and close dirptr
1084 if (numentries == 0) {
1085 dptr_close(&dptr_num);
1086 } else if(expect_close && status_len == 0) {
1087 /* Close the dptr - we know it's gone */
1088 dptr_close(&dptr_num);
1091 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1092 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1093 dptr_close(&dptr_num);
1096 if ((numentries == 0) && !mask_contains_wcard) {
1097 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1100 SSVAL(outbuf,smb_vwv0,numentries);
1101 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1102 SCVAL(smb_buf(outbuf),0,5);
1103 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1105 /* The replies here are never long name. */
1106 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1107 if (!allow_long_path_components) {
1108 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1111 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1112 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1114 outsize += DIR_STRUCT_SIZE*numentries;
1115 smb_setlen(outbuf,outsize - 4);
1117 if ((! *directory) && dptr_path(dptr_num))
1118 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1120 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1121 smb_fn_name(CVAL(inbuf,smb_com)),
1122 mask, directory, dirtype, numentries, maxentries ) );
1124 END_PROFILE(SMBsearch);
1128 /****************************************************************************
1129 Reply to a fclose (stop directory search).
1130 ****************************************************************************/
1132 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1141 BOOL path_contains_wcard = False;
1143 START_PROFILE(SMBfclose);
1145 if (lp_posix_pathnames()) {
1146 END_PROFILE(SMBfclose);
1147 return reply_unknown(inbuf, outbuf);
1150 outsize = set_message(outbuf,1,0,True);
1151 p = smb_buf(inbuf) + 1;
1152 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1153 if (!NT_STATUS_IS_OK(err)) {
1154 END_PROFILE(SMBfclose);
1155 return ERROR_NT(err);
1158 status_len = SVAL(p,0);
1161 if (status_len == 0) {
1162 END_PROFILE(SMBfclose);
1163 return ERROR_DOS(ERRSRV,ERRsrverror);
1166 memcpy(status,p,21);
1168 if(dptr_fetch(status+12,&dptr_num)) {
1169 /* Close the dptr - we know it's gone */
1170 dptr_close(&dptr_num);
1173 SSVAL(outbuf,smb_vwv0,0);
1175 DEBUG(3,("search close\n"));
1177 END_PROFILE(SMBfclose);
1181 /****************************************************************************
1183 ****************************************************************************/
1185 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1193 SMB_STRUCT_STAT sbuf;
1195 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1197 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1200 uint32 create_disposition;
1201 uint32 create_options = 0;
1203 START_PROFILE(SMBopen);
1205 deny_mode = SVAL(inbuf,smb_vwv0);
1207 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 END_PROFILE(SMBopen);
1210 return ERROR_NT(status);
1213 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1214 END_PROFILE(SMBopen);
1215 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1218 status = unix_convert(conn, fname, False, NULL, &sbuf);
1219 if (!NT_STATUS_IS_OK(status)) {
1220 END_PROFILE(SMBopen);
1221 return ERROR_NT(status);
1224 status = check_name(conn, fname);
1225 if (!NT_STATUS_IS_OK(status)) {
1226 END_PROFILE(SMBopen);
1227 return ERROR_NT(status);
1230 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1231 &access_mask, &share_mode, &create_disposition, &create_options)) {
1232 END_PROFILE(SMBopen);
1233 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1236 status = open_file_ntcreate(conn,fname,&sbuf,
1245 if (!NT_STATUS_IS_OK(status)) {
1246 END_PROFILE(SMBopen);
1247 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1248 /* We have re-scheduled this call. */
1251 return ERROR_NT(status);
1254 size = sbuf.st_size;
1255 fattr = dos_mode(conn,fname,&sbuf);
1256 mtime = sbuf.st_mtime;
1259 DEBUG(3,("attempt to open a directory %s\n",fname));
1260 close_file(fsp,ERROR_CLOSE);
1261 END_PROFILE(SMBopen);
1262 return ERROR_DOS(ERRDOS,ERRnoaccess);
1265 outsize = set_message(outbuf,7,0,True);
1266 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1267 SSVAL(outbuf,smb_vwv1,fattr);
1268 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1269 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1271 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1273 SIVAL(outbuf,smb_vwv4,(uint32)size);
1274 SSVAL(outbuf,smb_vwv6,deny_mode);
1276 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1277 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1280 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1281 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1283 END_PROFILE(SMBopen);
1287 /****************************************************************************
1288 Reply to an open and X.
1289 ****************************************************************************/
1291 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1294 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1295 int deny_mode = SVAL(inbuf,smb_vwv3);
1296 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1297 /* Breakout the oplock request bits so we can set the
1298 reply bits separately. */
1299 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1300 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1301 int oplock_request = ex_oplock_request | core_oplock_request;
1303 int smb_sattr = SVAL(inbuf,smb_vwv4);
1304 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1306 int smb_ofun = SVAL(inbuf,smb_vwv8);
1309 SMB_STRUCT_STAT sbuf;
1313 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1314 ssize_t retval = -1;
1317 uint32 create_disposition;
1318 uint32 create_options = 0;
1320 START_PROFILE(SMBopenX);
1322 /* If it's an IPC, pass off the pipe handler. */
1324 if (lp_nt_pipe_support()) {
1325 END_PROFILE(SMBopenX);
1326 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1328 END_PROFILE(SMBopenX);
1329 return ERROR_DOS(ERRSRV,ERRaccess);
1333 /* XXXX we need to handle passed times, sattr and flags */
1334 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 END_PROFILE(SMBopenX);
1337 return ERROR_NT(status);
1340 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1341 END_PROFILE(SMBopenX);
1342 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1345 status = unix_convert(conn, fname, False, NULL, &sbuf);
1346 if (!NT_STATUS_IS_OK(status)) {
1347 END_PROFILE(SMBopenX);
1348 return ERROR_NT(status);
1351 status = check_name(conn, fname);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 END_PROFILE(SMBopenX);
1354 return ERROR_NT(status);
1357 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1360 &create_disposition,
1362 END_PROFILE(SMBopenX);
1363 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1366 status = open_file_ntcreate(conn,fname,&sbuf,
1375 if (!NT_STATUS_IS_OK(status)) {
1376 END_PROFILE(SMBopenX);
1377 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1378 /* We have re-scheduled this call. */
1381 return ERROR_NT(status);
1384 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1385 if the file is truncated or created. */
1386 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1387 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1388 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1389 close_file(fsp,ERROR_CLOSE);
1390 END_PROFILE(SMBopenX);
1391 return ERROR_NT(NT_STATUS_DISK_FULL);
1393 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1395 close_file(fsp,ERROR_CLOSE);
1396 END_PROFILE(SMBopenX);
1397 return ERROR_NT(NT_STATUS_DISK_FULL);
1399 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1402 fattr = dos_mode(conn,fname,&sbuf);
1403 mtime = sbuf.st_mtime;
1405 close_file(fsp,ERROR_CLOSE);
1406 END_PROFILE(SMBopenX);
1407 return ERROR_DOS(ERRDOS,ERRnoaccess);
1410 /* If the caller set the extended oplock request bit
1411 and we granted one (by whatever means) - set the
1412 correct bit for extended oplock reply.
1415 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1416 smb_action |= EXTENDED_OPLOCK_GRANTED;
1419 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1420 smb_action |= EXTENDED_OPLOCK_GRANTED;
1423 /* If the caller set the core oplock request bit
1424 and we granted one (by whatever means) - set the
1425 correct bit for core oplock reply.
1428 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1429 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1432 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1433 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1436 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1437 set_message(outbuf,19,0,True);
1439 set_message(outbuf,15,0,True);
1441 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1442 SSVAL(outbuf,smb_vwv3,fattr);
1443 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1444 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1446 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1448 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1449 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1450 SSVAL(outbuf,smb_vwv11,smb_action);
1452 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1453 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1456 END_PROFILE(SMBopenX);
1457 return chain_reply(inbuf,outbuf,length,bufsize);
1460 /****************************************************************************
1461 Reply to a SMBulogoffX.
1462 conn POINTER CAN BE NULL HERE !
1463 ****************************************************************************/
1465 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1467 uint16 vuid = SVAL(inbuf,smb_uid);
1468 user_struct *vuser = get_valid_user_struct(vuid);
1469 START_PROFILE(SMBulogoffX);
1472 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1474 /* in user level security we are supposed to close any files
1475 open by this user */
1476 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1477 file_close_user(vuid);
1479 invalidate_vuid(vuid);
1481 set_message(outbuf,2,0,True);
1483 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1485 END_PROFILE(SMBulogoffX);
1486 return chain_reply(inbuf,outbuf,length,bufsize);
1489 /****************************************************************************
1490 Reply to a mknew or a create.
1491 ****************************************************************************/
1493 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1498 uint32 fattr = SVAL(inbuf,smb_vwv0);
1499 struct timespec ts[2];
1501 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1502 SMB_STRUCT_STAT sbuf;
1504 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1505 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1506 uint32 create_disposition;
1507 uint32 create_options = 0;
1509 START_PROFILE(SMBcreate);
1511 com = SVAL(inbuf,smb_com);
1513 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1515 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 END_PROFILE(SMBcreate);
1518 return ERROR_NT(status);
1521 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1522 END_PROFILE(SMBcreate);
1523 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1526 status = unix_convert(conn, fname, False, NULL, &sbuf);
1527 if (!NT_STATUS_IS_OK(status)) {
1528 END_PROFILE(SMBcreate);
1529 return ERROR_NT(status);
1532 status = check_name(conn, fname);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 END_PROFILE(SMBcreate);
1535 return ERROR_NT(status);
1538 if (fattr & aVOLID) {
1539 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1542 if(com == SMBmknew) {
1543 /* We should fail if file exists. */
1544 create_disposition = FILE_CREATE;
1546 /* Create if file doesn't exist, truncate if it does. */
1547 create_disposition = FILE_OVERWRITE_IF;
1550 /* Open file using ntcreate. */
1551 status = open_file_ntcreate(conn,fname,&sbuf,
1560 if (!NT_STATUS_IS_OK(status)) {
1561 END_PROFILE(SMBcreate);
1562 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1563 /* We have re-scheduled this call. */
1566 return ERROR_NT(status);
1569 ts[0] = get_atimespec(&sbuf); /* atime. */
1570 file_ntimes(conn, fname, ts);
1572 outsize = set_message(outbuf,1,0,True);
1573 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1575 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1576 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1579 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1580 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1583 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1584 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1586 END_PROFILE(SMBcreate);
1590 /****************************************************************************
1591 Reply to a create temporary file.
1592 ****************************************************************************/
1594 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1598 uint32 fattr = SVAL(inbuf,smb_vwv0);
1600 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1602 SMB_STRUCT_STAT sbuf;
1605 unsigned int namelen;
1607 START_PROFILE(SMBctemp);
1609 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 END_PROFILE(SMBctemp);
1612 return ERROR_NT(status);
1615 pstrcat(fname,"/TMXXXXXX");
1617 pstrcat(fname,"TMXXXXXX");
1620 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1621 END_PROFILE(SMBctemp);
1622 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1625 status = unix_convert(conn, fname, False, NULL, &sbuf);
1626 if (!NT_STATUS_IS_OK(status)) {
1627 END_PROFILE(SMBctemp);
1628 return ERROR_NT(status);
1631 status = check_name(conn, fname);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 END_PROFILE(SMBctemp);
1634 return ERROR_NT(status);
1637 tmpfd = smb_mkstemp(fname);
1639 END_PROFILE(SMBctemp);
1640 return(UNIXERROR(ERRDOS,ERRnoaccess));
1643 SMB_VFS_STAT(conn,fname,&sbuf);
1645 /* We should fail if file does not exist. */
1646 status = open_file_ntcreate(conn,fname,&sbuf,
1647 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1648 FILE_SHARE_READ|FILE_SHARE_WRITE,
1655 /* close fd from smb_mkstemp() */
1658 if (!NT_STATUS_IS_OK(status)) {
1659 END_PROFILE(SMBctemp);
1660 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1661 /* We have re-scheduled this call. */
1664 return ERROR_NT(status);
1667 outsize = set_message(outbuf,1,0,True);
1668 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1670 /* the returned filename is relative to the directory */
1671 s = strrchr_m(fname, '/');
1678 p = smb_buf(outbuf);
1680 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1681 thing in the byte section. JRA */
1682 SSVALS(p, 0, -1); /* what is this? not in spec */
1684 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1686 outsize = set_message_end(outbuf, p);
1688 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1689 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1692 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1693 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1696 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1697 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1698 (unsigned int)sbuf.st_mode ) );
1700 END_PROFILE(SMBctemp);
1704 /*******************************************************************
1705 Check if a user is allowed to rename a file.
1706 ********************************************************************/
1708 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1714 if (!CAN_WRITE(conn)) {
1715 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1718 fmode = dos_mode(conn,fname,pst);
1719 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1720 return NT_STATUS_NO_SUCH_FILE;
1723 if (S_ISDIR(pst->st_mode)) {
1724 return NT_STATUS_OK;
1727 status = open_file_ntcreate(conn, fname, pst,
1729 FILE_SHARE_READ|FILE_SHARE_WRITE,
1732 FILE_ATTRIBUTE_NORMAL,
1736 if (!NT_STATUS_IS_OK(status)) {
1739 close_file(fsp,NORMAL_CLOSE);
1740 return NT_STATUS_OK;
1743 /*******************************************************************
1744 Check if a user is allowed to delete a file.
1745 ********************************************************************/
1747 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1748 uint32 dirtype, BOOL can_defer)
1750 SMB_STRUCT_STAT sbuf;
1753 uint32 dirtype_orig = dirtype;
1756 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1758 if (!CAN_WRITE(conn)) {
1759 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1762 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1763 return map_nt_error_from_unix(errno);
1766 fattr = dos_mode(conn,fname,&sbuf);
1768 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1769 dirtype = aDIR|aARCH|aRONLY;
1772 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1774 return NT_STATUS_NO_SUCH_FILE;
1777 if (!dir_check_ftype(conn, fattr, dirtype)) {
1779 return NT_STATUS_FILE_IS_A_DIRECTORY;
1781 return NT_STATUS_NO_SUCH_FILE;
1784 if (dirtype_orig & 0x8000) {
1785 /* These will never be set for POSIX. */
1786 return NT_STATUS_NO_SUCH_FILE;
1790 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1791 return NT_STATUS_FILE_IS_A_DIRECTORY;
1794 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1795 return NT_STATUS_NO_SUCH_FILE;
1798 if (dirtype & 0xFF00) {
1799 /* These will never be set for POSIX. */
1800 return NT_STATUS_NO_SUCH_FILE;
1805 return NT_STATUS_NO_SUCH_FILE;
1808 /* Can't delete a directory. */
1810 return NT_STATUS_FILE_IS_A_DIRECTORY;
1815 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1816 return NT_STATUS_OBJECT_NAME_INVALID;
1817 #endif /* JRATEST */
1819 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1821 On a Windows share, a file with read-only dosmode can be opened with
1822 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1823 fails with NT_STATUS_CANNOT_DELETE error.
1825 This semantic causes a problem that a user can not
1826 rename a file with read-only dosmode on a Samba share
1827 from a Windows command prompt (i.e. cmd.exe, but can rename
1828 from Windows Explorer).
1831 if (!lp_delete_readonly(SNUM(conn))) {
1832 if (fattr & aRONLY) {
1833 return NT_STATUS_CANNOT_DELETE;
1837 /* On open checks the open itself will check the share mode, so
1838 don't do it here as we'll get it wrong. */
1840 status = open_file_ntcreate(conn, fname, &sbuf,
1845 FILE_ATTRIBUTE_NORMAL,
1846 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1849 if (NT_STATUS_IS_OK(status)) {
1850 close_file(fsp,NORMAL_CLOSE);
1855 /****************************************************************************
1856 The guts of the unlink command, split out so it may be called by the NT SMB
1858 ****************************************************************************/
1860 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1861 char *name, BOOL has_wild, BOOL can_defer)
1867 NTSTATUS status = NT_STATUS_OK;
1868 SMB_STRUCT_STAT sbuf;
1870 *directory = *mask = 0;
1872 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1873 if (!NT_STATUS_IS_OK(status)) {
1877 p = strrchr_m(name,'/');
1879 pstrcpy(directory,".");
1883 pstrcpy(directory,name);
1888 * We should only check the mangled cache
1889 * here if unix_convert failed. This means
1890 * that the path in 'mask' doesn't exist
1891 * on the file system and so we need to look
1892 * for a possible mangle. This patch from
1893 * Tine Smukavec <valentin.smukavec@hermes.si>.
1896 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1897 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1900 pstrcat(directory,"/");
1901 pstrcat(directory,mask);
1903 dirtype = FILE_ATTRIBUTE_NORMAL;
1906 status = check_name(conn, directory);
1907 if (!NT_STATUS_IS_OK(status)) {
1911 status = can_delete(conn,directory,dirtype,can_defer);
1912 if (!NT_STATUS_IS_OK(status)) {
1916 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1918 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1919 FILE_NOTIFY_CHANGE_FILE_NAME,
1923 struct smb_Dir *dir_hnd = NULL;
1927 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
1928 return NT_STATUS_OBJECT_NAME_INVALID;
1931 if (strequal(mask,"????????.???")) {
1935 status = check_name(conn, directory);
1936 if (!NT_STATUS_IS_OK(status)) {
1940 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1941 if (dir_hnd == NULL) {
1942 return map_nt_error_from_unix(errno);
1945 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1946 the pattern matches against the long name, otherwise the short name
1947 We don't implement this yet XXXX
1950 status = NT_STATUS_NO_SUCH_FILE;
1952 while ((dname = ReadDirName(dir_hnd, &offset))) {
1955 pstrcpy(fname,dname);
1957 if (!is_visible_file(conn, directory, dname, &st, True)) {
1961 /* Quick check for "." and ".." */
1962 if (fname[0] == '.') {
1963 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1968 if(!mask_match(fname, mask, conn->case_sensitive)) {
1972 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1974 status = check_name(conn, fname);
1975 if (!NT_STATUS_IS_OK(status)) {
1979 status = can_delete(conn, fname, dirtype, can_defer);
1980 if (!NT_STATUS_IS_OK(status)) {
1983 if (SMB_VFS_UNLINK(conn,fname) == 0) {
1985 DEBUG(3,("unlink_internals: succesful unlink "
1987 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1988 FILE_NOTIFY_CHANGE_FILE_NAME,
1996 if (count == 0 && NT_STATUS_IS_OK(status)) {
1997 status = map_nt_error_from_unix(errno);
2003 /****************************************************************************
2005 ****************************************************************************/
2007 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2014 BOOL path_contains_wcard = False;
2016 START_PROFILE(SMBunlink);
2018 dirtype = SVAL(inbuf,smb_vwv0);
2020 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 END_PROFILE(SMBunlink);
2023 return ERROR_NT(status);
2026 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
2027 END_PROFILE(SMBunlink);
2028 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2031 DEBUG(3,("reply_unlink : %s\n",name));
2033 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2035 if (!NT_STATUS_IS_OK(status)) {
2036 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2037 /* We have re-scheduled this call. */
2040 return ERROR_NT(status);
2043 outsize = set_message(outbuf,0,0,False);
2045 END_PROFILE(SMBunlink);
2049 /****************************************************************************
2051 ****************************************************************************/
2053 static void fail_readraw(void)
2056 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2058 exit_server_cleanly(errstr);
2061 #if defined(WITH_SENDFILE)
2062 /****************************************************************************
2063 Fake (read/write) sendfile. Returns -1 on read or write fail.
2064 ****************************************************************************/
2066 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2070 /* Paranioa check... */
2071 if (nread > bufsize) {
2076 ret = read_file(fsp,buf,startpos,nread);
2082 /* If we had a short read, fill with zeros. */
2084 memset(buf, '\0', nread - ret);
2087 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2091 return (ssize_t)nread;
2095 /****************************************************************************
2096 Use sendfile in readbraw.
2097 ****************************************************************************/
2099 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2100 ssize_t mincount, char *outbuf, int out_buffsize)
2104 #if defined(WITH_SENDFILE)
2106 * We can only use sendfile on a non-chained packet
2107 * but we can use on a non-oplocked file. tridge proved this
2108 * on a train in Germany :-). JRA.
2109 * reply_readbraw has already checked the length.
2112 if ( (chain_size == 0) && (nread > 0) &&
2113 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2116 _smb_setlen(outbuf,nread);
2117 header.data = (uint8 *)outbuf;
2121 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2122 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2123 if (errno == ENOSYS) {
2124 goto normal_readbraw;
2128 * Special hack for broken Linux with no working sendfile. If we
2129 * return EINTR we sent the header but not the rest of the data.
2130 * Fake this up by doing read/write calls.
2132 if (errno == EINTR) {
2133 /* Ensure we don't do this again. */
2134 set_use_sendfile(SNUM(conn), False);
2135 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2137 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2138 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2139 fsp->fsp_name, strerror(errno) ));
2140 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2145 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2146 fsp->fsp_name, strerror(errno) ));
2147 exit_server_cleanly("send_file_readbraw sendfile failed");
2157 ret = read_file(fsp,outbuf+4,startpos,nread);
2158 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2167 _smb_setlen(outbuf,ret);
2168 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2172 /****************************************************************************
2173 Reply to a readbraw (core+ protocol).
2174 ****************************************************************************/
2176 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2178 ssize_t maxcount,mincount;
2181 char *header = outbuf;
2183 START_PROFILE(SMBreadbraw);
2185 if (srv_is_signing_active()) {
2186 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2190 * Special check if an oplock break has been issued
2191 * and the readraw request croses on the wire, we must
2192 * return a zero length response here.
2195 fsp = file_fsp(inbuf,smb_vwv0);
2197 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2199 * fsp could be NULL here so use the value from the packet. JRA.
2201 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2202 _smb_setlen(header,0);
2203 if (write_data(smbd_server_fd(),header,4) != 4)
2205 END_PROFILE(SMBreadbraw);
2209 CHECK_FSP(fsp,conn);
2211 flush_write_cache(fsp, READRAW_FLUSH);
2213 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2214 if(CVAL(inbuf,smb_wct) == 10) {
2216 * This is a large offset (64 bit) read.
2218 #ifdef LARGE_SMB_OFF_T
2220 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2222 #else /* !LARGE_SMB_OFF_T */
2225 * Ensure we haven't been sent a >32 bit offset.
2228 if(IVAL(inbuf,smb_vwv8) != 0) {
2229 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2230 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2231 _smb_setlen(header,0);
2232 if (write_data(smbd_server_fd(),header,4) != 4)
2234 END_PROFILE(SMBreadbraw);
2238 #endif /* LARGE_SMB_OFF_T */
2241 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2242 _smb_setlen(header,0);
2243 if (write_data(smbd_server_fd(),header,4) != 4)
2245 END_PROFILE(SMBreadbraw);
2249 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2250 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2252 /* ensure we don't overrun the packet size */
2253 maxcount = MIN(65535,maxcount);
2255 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2259 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2263 if (startpos >= size) {
2266 nread = MIN(maxcount,(size - startpos));
2270 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2271 if (nread < mincount)
2275 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2276 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2278 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2280 DEBUG(5,("readbraw finished\n"));
2281 END_PROFILE(SMBreadbraw);
2286 #define DBGC_CLASS DBGC_LOCKING
2288 /****************************************************************************
2289 Reply to a lockread (core+ protocol).
2290 ****************************************************************************/
2292 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2300 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2301 struct byte_range_lock *br_lck = NULL;
2302 START_PROFILE(SMBlockread);
2304 CHECK_FSP(fsp,conn);
2305 if (!CHECK_READ(fsp,inbuf)) {
2306 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2309 release_level_2_oplocks_on_change(fsp);
2311 numtoread = SVAL(inbuf,smb_vwv1);
2312 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2314 outsize = set_message(outbuf,5,3,True);
2315 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2316 data = smb_buf(outbuf) + 3;
2319 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2320 * protocol request that predates the read/write lock concept.
2321 * Thus instead of asking for a read lock here we need to ask
2322 * for a write lock. JRA.
2323 * Note that the requested lock size is unaffected by max_recv.
2326 br_lck = do_lock(fsp,
2327 (uint32)SVAL(inbuf,smb_pid),
2328 (SMB_BIG_UINT)numtoread,
2329 (SMB_BIG_UINT)startpos,
2332 False, /* Non-blocking lock. */
2334 TALLOC_FREE(br_lck);
2336 if (NT_STATUS_V(status)) {
2337 END_PROFILE(SMBlockread);
2338 return ERROR_NT(status);
2342 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2345 if (numtoread > max_recv) {
2346 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2347 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2348 (unsigned int)numtoread, (unsigned int)max_recv ));
2349 numtoread = MIN(numtoread,max_recv);
2351 nread = read_file(fsp,data,startpos,numtoread);
2354 END_PROFILE(SMBlockread);
2355 return(UNIXERROR(ERRDOS,ERRnoaccess));
2359 SSVAL(outbuf,smb_vwv0,nread);
2360 SSVAL(outbuf,smb_vwv5,nread+3);
2361 SSVAL(smb_buf(outbuf),1,nread);
2363 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2364 fsp->fnum, (int)numtoread, (int)nread));
2366 END_PROFILE(SMBlockread);
2371 #define DBGC_CLASS DBGC_ALL
2373 /****************************************************************************
2375 ****************************************************************************/
2377 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2384 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2385 START_PROFILE(SMBread);
2387 CHECK_FSP(fsp,conn);
2388 if (!CHECK_READ(fsp,inbuf)) {
2389 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2392 numtoread = SVAL(inbuf,smb_vwv1);
2393 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2395 outsize = set_message(outbuf,5,3,True);
2396 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2398 * The requested read size cannot be greater than max_recv. JRA.
2400 if (numtoread > max_recv) {
2401 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2402 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2403 (unsigned int)numtoread, (unsigned int)max_recv ));
2404 numtoread = MIN(numtoread,max_recv);
2407 data = smb_buf(outbuf) + 3;
2409 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2410 END_PROFILE(SMBread);
2411 return ERROR_DOS(ERRDOS,ERRlock);
2415 nread = read_file(fsp,data,startpos,numtoread);
2418 END_PROFILE(SMBread);
2419 return(UNIXERROR(ERRDOS,ERRnoaccess));
2423 SSVAL(outbuf,smb_vwv0,nread);
2424 SSVAL(outbuf,smb_vwv5,nread+3);
2425 SCVAL(smb_buf(outbuf),0,1);
2426 SSVAL(smb_buf(outbuf),1,nread);
2428 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2429 fsp->fnum, (int)numtoread, (int)nread ) );
2431 END_PROFILE(SMBread);
2435 /****************************************************************************
2436 Reply to a read and X - possibly using sendfile.
2437 ****************************************************************************/
2439 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2440 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2444 char *data = smb_buf(outbuf);
2446 #if defined(WITH_SENDFILE)
2448 * We can only use sendfile on a non-chained packet
2449 * but we can use on a non-oplocked file. tridge proved this
2450 * on a train in Germany :-). JRA.
2453 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2454 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2455 SMB_STRUCT_STAT sbuf;
2458 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2459 return(UNIXERROR(ERRDOS,ERRnoaccess));
2461 if (startpos > sbuf.st_size)
2464 if (smb_maxcnt > (sbuf.st_size - startpos))
2465 smb_maxcnt = (sbuf.st_size - startpos);
2467 if (smb_maxcnt == 0)
2471 * Set up the packet header before send. We
2472 * assume here the sendfile will work (get the
2473 * correct amount of data).
2476 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2477 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2478 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2479 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2480 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2481 SCVAL(outbuf,smb_vwv0,0xFF);
2482 set_message(outbuf,12,smb_maxcnt,False);
2483 header.data = (uint8 *)outbuf;
2484 header.length = data - outbuf;
2487 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2488 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2489 if (errno == ENOSYS) {
2494 * Special hack for broken Linux with no working sendfile. If we
2495 * return EINTR we sent the header but not the rest of the data.
2496 * Fake this up by doing read/write calls.
2499 if (errno == EINTR) {
2500 /* Ensure we don't do this again. */
2501 set_use_sendfile(SNUM(conn), False);
2502 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2504 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2505 len_outbuf - (data-outbuf))) == -1) {
2506 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2507 fsp->fsp_name, strerror(errno) ));
2508 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2510 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2511 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2512 /* Returning -1 here means successful sendfile. */
2516 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2517 fsp->fsp_name, strerror(errno) ));
2518 exit_server_cleanly("send_file_readX sendfile failed");
2521 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2522 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2523 /* Returning -1 here means successful sendfile. */
2531 nread = read_file(fsp,data,startpos,smb_maxcnt);
2534 return(UNIXERROR(ERRDOS,ERRnoaccess));
2537 outsize = set_message(outbuf,12,nread,False);
2538 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2539 SSVAL(outbuf,smb_vwv5,nread);
2540 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2541 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2542 SSVAL(smb_buf(outbuf),-2,nread);
2544 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2545 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2547 /* Returning the number of bytes we want to send back - including header. */
2551 /****************************************************************************
2552 Reply to a read and X.
2553 ****************************************************************************/
2555 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2557 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2558 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2560 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2562 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2565 START_PROFILE(SMBreadX);
2567 /* If it's an IPC, pass off the pipe handler. */
2569 END_PROFILE(SMBreadX);
2570 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2573 CHECK_FSP(fsp,conn);
2574 if (!CHECK_READ(fsp,inbuf)) {
2575 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2578 set_message(outbuf,12,0,True);
2580 if (global_client_caps & CAP_LARGE_READX) {
2581 if (SVAL(inbuf,smb_vwv7) == 1) {
2582 smb_maxcnt |= (1<<16);
2584 if (smb_maxcnt > BUFFER_SIZE) {
2585 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2586 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2587 END_PROFILE(SMBreadX);
2588 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2592 if(CVAL(inbuf,smb_wct) == 12) {
2593 #ifdef LARGE_SMB_OFF_T
2595 * This is a large offset (64 bit) read.
2597 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2599 #else /* !LARGE_SMB_OFF_T */
2602 * Ensure we haven't been sent a >32 bit offset.
2605 if(IVAL(inbuf,smb_vwv10) != 0) {
2606 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2607 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2608 END_PROFILE(SMBreadX);
2609 return ERROR_DOS(ERRDOS,ERRbadaccess);
2612 #endif /* LARGE_SMB_OFF_T */
2616 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2617 END_PROFILE(SMBreadX);
2618 return ERROR_DOS(ERRDOS,ERRlock);
2621 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2622 END_PROFILE(SMBreadX);
2626 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2628 nread = chain_reply(inbuf,outbuf,length,bufsize);
2630 END_PROFILE(SMBreadX);
2634 /****************************************************************************
2635 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2636 ****************************************************************************/
2638 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2641 ssize_t total_written=0;
2642 size_t numtowrite=0;
2647 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2649 START_PROFILE(SMBwritebraw);
2651 if (srv_is_signing_active()) {
2652 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2655 CHECK_FSP(fsp,conn);
2656 if (!CHECK_WRITE(fsp)) {
2657 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2660 tcount = IVAL(inbuf,smb_vwv1);
2661 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2662 write_through = BITSETW(inbuf+smb_vwv7,0);
2664 /* We have to deal with slightly different formats depending
2665 on whether we are using the core+ or lanman1.0 protocol */
2667 if(Protocol <= PROTOCOL_COREPLUS) {
2668 numtowrite = SVAL(smb_buf(inbuf),-2);
2669 data = smb_buf(inbuf);
2671 numtowrite = SVAL(inbuf,smb_vwv10);
2672 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2675 /* force the error type */
2676 SCVAL(inbuf,smb_com,SMBwritec);
2677 SCVAL(outbuf,smb_com,SMBwritec);
2679 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2680 END_PROFILE(SMBwritebraw);
2681 return(ERROR_DOS(ERRDOS,ERRlock));
2685 nwritten = write_file(fsp,data,startpos,numtowrite);
2687 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2688 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2690 if (nwritten < (ssize_t)numtowrite) {
2691 END_PROFILE(SMBwritebraw);
2692 return(UNIXERROR(ERRHRD,ERRdiskfull));
2695 total_written = nwritten;
2697 /* Return a message to the redirector to tell it to send more bytes */
2698 SCVAL(outbuf,smb_com,SMBwritebraw);
2699 SSVALS(outbuf,smb_vwv0,-1);
2700 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2702 if (!send_smb(smbd_server_fd(),outbuf))
2703 exit_server_cleanly("reply_writebraw: send_smb failed.");
2705 /* Now read the raw data into the buffer and write it */
2706 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2707 exit_server_cleanly("secondary writebraw failed");
2710 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2711 numtowrite = smb_len(inbuf);
2713 /* Set up outbuf to return the correct return */
2714 outsize = set_message(outbuf,1,0,True);
2715 SCVAL(outbuf,smb_com,SMBwritec);
2717 if (numtowrite != 0) {
2719 if (numtowrite > BUFFER_SIZE) {
2720 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2721 (unsigned int)numtowrite ));
2722 exit_server_cleanly("secondary writebraw failed");
2725 if (tcount > nwritten+numtowrite) {
2726 DEBUG(3,("Client overestimated the write %d %d %d\n",
2727 (int)tcount,(int)nwritten,(int)numtowrite));
2730 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2731 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2733 exit_server_cleanly("secondary writebraw failed");
2736 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2737 if (nwritten == -1) {
2738 END_PROFILE(SMBwritebraw);
2739 return(UNIXERROR(ERRHRD,ERRdiskfull));
2742 if (nwritten < (ssize_t)numtowrite) {
2743 SCVAL(outbuf,smb_rcls,ERRHRD);
2744 SSVAL(outbuf,smb_err,ERRdiskfull);
2748 total_written += nwritten;
2751 SSVAL(outbuf,smb_vwv0,total_written);
2753 sync_file(conn, fsp, write_through);
2755 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2756 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2758 /* we won't return a status if write through is not selected - this follows what WfWg does */
2759 END_PROFILE(SMBwritebraw);
2760 if (!write_through && total_written==tcount) {
2762 #if RABBIT_PELLET_FIX
2764 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2765 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2767 if (!send_keepalive(smbd_server_fd()))
2768 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2777 #define DBGC_CLASS DBGC_LOCKING
2779 /****************************************************************************
2780 Reply to a writeunlock (core+).
2781 ****************************************************************************/
2783 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2784 int size, int dum_buffsize)
2786 ssize_t nwritten = -1;
2790 NTSTATUS status = NT_STATUS_OK;
2791 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2793 START_PROFILE(SMBwriteunlock);
2795 CHECK_FSP(fsp,conn);
2796 if (!CHECK_WRITE(fsp)) {
2797 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2800 numtowrite = SVAL(inbuf,smb_vwv1);
2801 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2802 data = smb_buf(inbuf) + 3;
2804 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2805 END_PROFILE(SMBwriteunlock);
2806 return ERROR_DOS(ERRDOS,ERRlock);
2809 /* The special X/Open SMB protocol handling of
2810 zero length writes is *NOT* done for
2812 if(numtowrite == 0) {
2815 nwritten = write_file(fsp,data,startpos,numtowrite);
2818 sync_file(conn, fsp, False /* write through */);
2820 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2821 END_PROFILE(SMBwriteunlock);
2822 return(UNIXERROR(ERRHRD,ERRdiskfull));
2826 status = do_unlock(fsp,
2827 (uint32)SVAL(inbuf,smb_pid),
2828 (SMB_BIG_UINT)numtowrite,
2829 (SMB_BIG_UINT)startpos,
2832 if (NT_STATUS_V(status)) {
2833 END_PROFILE(SMBwriteunlock);
2834 return ERROR_NT(status);
2838 outsize = set_message(outbuf,1,0,True);
2840 SSVAL(outbuf,smb_vwv0,nwritten);
2842 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2843 fsp->fnum, (int)numtowrite, (int)nwritten));
2845 END_PROFILE(SMBwriteunlock);
2850 #define DBGC_CLASS DBGC_ALL
2852 /****************************************************************************
2854 ****************************************************************************/
2856 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2859 ssize_t nwritten = -1;
2862 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2864 START_PROFILE(SMBwrite);
2866 /* If it's an IPC, pass off the pipe handler. */
2868 END_PROFILE(SMBwrite);
2869 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2872 CHECK_FSP(fsp,conn);
2873 if (!CHECK_WRITE(fsp)) {
2874 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2877 numtowrite = SVAL(inbuf,smb_vwv1);
2878 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2879 data = smb_buf(inbuf) + 3;
2881 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2882 END_PROFILE(SMBwrite);
2883 return ERROR_DOS(ERRDOS,ERRlock);
2887 * X/Open SMB protocol says that if smb_vwv1 is
2888 * zero then the file size should be extended or
2889 * truncated to the size given in smb_vwv[2-3].
2892 if(numtowrite == 0) {
2894 * This is actually an allocate call, and set EOF. JRA.
2896 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2898 END_PROFILE(SMBwrite);
2899 return ERROR_NT(NT_STATUS_DISK_FULL);
2901 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2903 END_PROFILE(SMBwrite);
2904 return ERROR_NT(NT_STATUS_DISK_FULL);
2907 nwritten = write_file(fsp,data,startpos,numtowrite);
2909 sync_file(conn, fsp, False);
2911 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2912 END_PROFILE(SMBwrite);
2913 return(UNIXERROR(ERRHRD,ERRdiskfull));
2916 outsize = set_message(outbuf,1,0,True);
2918 SSVAL(outbuf,smb_vwv0,nwritten);
2920 if (nwritten < (ssize_t)numtowrite) {
2921 SCVAL(outbuf,smb_rcls,ERRHRD);
2922 SSVAL(outbuf,smb_err,ERRdiskfull);
2925 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2927 END_PROFILE(SMBwrite);
2931 /****************************************************************************
2932 Reply to a write and X.
2933 ****************************************************************************/
2935 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2937 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2938 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2939 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2940 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2941 ssize_t nwritten = -1;
2942 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2943 unsigned int smblen = smb_len(inbuf);
2945 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2946 START_PROFILE(SMBwriteX);
2948 /* If it's an IPC, pass off the pipe handler. */
2950 END_PROFILE(SMBwriteX);
2951 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2954 CHECK_FSP(fsp,conn);
2955 if (!CHECK_WRITE(fsp)) {
2956 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2959 set_message(outbuf,6,0,True);
2961 /* Deal with possible LARGE_WRITEX */
2963 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2966 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2967 END_PROFILE(SMBwriteX);
2968 return ERROR_DOS(ERRDOS,ERRbadmem);
2971 data = smb_base(inbuf) + smb_doff;
2973 if(CVAL(inbuf,smb_wct) == 14) {
2974 #ifdef LARGE_SMB_OFF_T
2976 * This is a large offset (64 bit) write.
2978 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2980 #else /* !LARGE_SMB_OFF_T */
2983 * Ensure we haven't been sent a >32 bit offset.
2986 if(IVAL(inbuf,smb_vwv12) != 0) {
2987 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2988 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2989 END_PROFILE(SMBwriteX);
2990 return ERROR_DOS(ERRDOS,ERRbadaccess);
2993 #endif /* LARGE_SMB_OFF_T */
2996 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2997 END_PROFILE(SMBwriteX);
2998 return ERROR_DOS(ERRDOS,ERRlock);
3001 /* X/Open SMB protocol says that, unlike SMBwrite
3002 if the length is zero then NO truncation is
3003 done, just a write of zero. To truncate a file,
3006 if(numtowrite == 0) {
3010 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3011 fsp,data,startpos,numtowrite)) {
3012 END_PROFILE(SMBwriteX);
3016 nwritten = write_file(fsp,data,startpos,numtowrite);
3019 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3020 END_PROFILE(SMBwriteX);
3021 return(UNIXERROR(ERRHRD,ERRdiskfull));
3024 SSVAL(outbuf,smb_vwv2,nwritten);
3026 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3028 if (nwritten < (ssize_t)numtowrite) {
3029 SCVAL(outbuf,smb_rcls,ERRHRD);
3030 SSVAL(outbuf,smb_err,ERRdiskfull);
3033 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3034 fsp->fnum, (int)numtowrite, (int)nwritten));
3036 sync_file(conn, fsp, write_through);
3038 END_PROFILE(SMBwriteX);
3039 return chain_reply(inbuf,outbuf,length,bufsize);
3042 /****************************************************************************
3044 ****************************************************************************/
3046 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3052 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3053 START_PROFILE(SMBlseek);
3055 CHECK_FSP(fsp,conn);
3057 flush_write_cache(fsp, SEEK_FLUSH);
3059 mode = SVAL(inbuf,smb_vwv1) & 3;
3060 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3061 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3070 res = fsp->fh->pos + startpos;
3081 if (umode == SEEK_END) {
3082 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3083 if(errno == EINVAL) {
3084 SMB_OFF_T current_pos = startpos;
3085 SMB_STRUCT_STAT sbuf;
3087 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3088 END_PROFILE(SMBlseek);
3089 return(UNIXERROR(ERRDOS,ERRnoaccess));
3092 current_pos += sbuf.st_size;
3094 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3099 END_PROFILE(SMBlseek);
3100 return(UNIXERROR(ERRDOS,ERRnoaccess));
3106 outsize = set_message(outbuf,2,0,True);
3107 SIVAL(outbuf,smb_vwv0,res);
3109 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3110 fsp->fnum, (double)startpos, (double)res, mode));
3112 END_PROFILE(SMBlseek);
3116 /****************************************************************************
3118 ****************************************************************************/
3120 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3122 int outsize = set_message(outbuf,0,0,False);
3123 uint16 fnum = SVAL(inbuf,smb_vwv0);
3124 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3125 START_PROFILE(SMBflush);
3128 CHECK_FSP(fsp,conn);
3131 file_sync_all(conn);
3133 sync_file(conn,fsp, True);
3136 DEBUG(3,("flush\n"));
3137 END_PROFILE(SMBflush);
3141 /****************************************************************************
3143 conn POINTER CAN BE NULL HERE !
3144 ****************************************************************************/
3146 int reply_exit(connection_struct *conn,
3147 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3150 START_PROFILE(SMBexit);
3152 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3154 outsize = set_message(outbuf,0,0,False);
3156 DEBUG(3,("exit\n"));
3158 END_PROFILE(SMBexit);
3162 /****************************************************************************
3163 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3164 ****************************************************************************/
3166 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3169 NTSTATUS status = NT_STATUS_OK;
3171 files_struct *fsp = NULL;
3172 START_PROFILE(SMBclose);
3174 outsize = set_message(outbuf,0,0,False);
3176 /* If it's an IPC, pass off to the pipe handler. */
3178 END_PROFILE(SMBclose);
3179 return reply_pipe_close(conn, inbuf,outbuf);
3182 fsp = file_fsp(inbuf,smb_vwv0);
3185 * We can only use CHECK_FSP if we know it's not a directory.
3188 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3189 END_PROFILE(SMBclose);
3190 return ERROR_DOS(ERRDOS,ERRbadfid);
3193 if(fsp->is_directory) {
3195 * Special case - close NT SMB directory handle.
3197 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3198 status = close_file(fsp,NORMAL_CLOSE);
3201 * Close ordinary file.
3204 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3205 fsp->fh->fd, fsp->fnum,
3206 conn->num_files_open));
3209 * Take care of any time sent in the close.
3212 fsp_set_pending_modtime(fsp,
3213 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3216 * close_file() returns the unix errno if an error
3217 * was detected on close - normally this is due to
3218 * a disk full error. If not then it was probably an I/O error.
3221 status = close_file(fsp,NORMAL_CLOSE);
3224 if(!NT_STATUS_IS_OK(status)) {
3225 END_PROFILE(SMBclose);
3226 return ERROR_NT(status);
3229 END_PROFILE(SMBclose);
3233 /****************************************************************************
3234 Reply to a writeclose (Core+ protocol).
3235 ****************************************************************************/
3237 int reply_writeclose(connection_struct *conn,
3238 char *inbuf,char *outbuf, int size, int dum_buffsize)
3241 ssize_t nwritten = -1;
3243 NTSTATUS close_status = NT_STATUS_OK;
3246 struct timespec mtime;
3247 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3248 START_PROFILE(SMBwriteclose);
3250 CHECK_FSP(fsp,conn);
3251 if (!CHECK_WRITE(fsp)) {
3252 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3255 numtowrite = SVAL(inbuf,smb_vwv1);
3256 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3257 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3258 data = smb_buf(inbuf) + 1;
3260 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3261 END_PROFILE(SMBwriteclose);
3262 return ERROR_DOS(ERRDOS,ERRlock);
3265 nwritten = write_file(fsp,data,startpos,numtowrite);
3267 set_filetime(conn, fsp->fsp_name, mtime);
3270 * More insanity. W2K only closes the file if writelen > 0.
3275 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3277 close_status = close_file(fsp,NORMAL_CLOSE);
3280 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3281 fsp->fnum, (int)numtowrite, (int)nwritten,
3282 conn->num_files_open));
3284 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3285 END_PROFILE(SMBwriteclose);
3286 return(UNIXERROR(ERRHRD,ERRdiskfull));
3289 if(!NT_STATUS_IS_OK(close_status)) {
3290 END_PROFILE(SMBwriteclose);
3291 return ERROR_NT(close_status);
3294 outsize = set_message(outbuf,1,0,True);
3296 SSVAL(outbuf,smb_vwv0,nwritten);
3297 END_PROFILE(SMBwriteclose);
3302 #define DBGC_CLASS DBGC_LOCKING
3304 /****************************************************************************
3306 ****************************************************************************/
3308 int reply_lock(connection_struct *conn,
3309 char *inbuf,char *outbuf, int length, int dum_buffsize)
3311 int outsize = set_message(outbuf,0,0,False);
3312 SMB_BIG_UINT count,offset;
3314 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3315 struct byte_range_lock *br_lck = NULL;
3317 START_PROFILE(SMBlock);
3319 CHECK_FSP(fsp,conn);
3321 release_level_2_oplocks_on_change(fsp);
3323 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3324 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3326 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3327 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3329 br_lck = do_lock(fsp,
3330 (uint32)SVAL(inbuf,smb_pid),
3335 False, /* Non-blocking lock. */
3338 TALLOC_FREE(br_lck);
3340 if (NT_STATUS_V(status)) {
3341 END_PROFILE(SMBlock);
3342 return ERROR_NT(status);
3345 END_PROFILE(SMBlock);
3349 /****************************************************************************
3351 ****************************************************************************/
3353 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3356 int outsize = set_message(outbuf,0,0,False);
3357 SMB_BIG_UINT count,offset;
3359 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3360 START_PROFILE(SMBunlock);
3362 CHECK_FSP(fsp,conn);
3364 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3365 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3367 status = do_unlock(fsp,
3368 (uint32)SVAL(inbuf,smb_pid),
3373 if (NT_STATUS_V(status)) {
3374 END_PROFILE(SMBunlock);
3375 return ERROR_NT(status);
3378 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3379 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3381 END_PROFILE(SMBunlock);
3386 #define DBGC_CLASS DBGC_ALL
3388 /****************************************************************************
3390 conn POINTER CAN BE NULL HERE !
3391 ****************************************************************************/
3393 int reply_tdis(connection_struct *conn,
3394 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3396 int outsize = set_message(outbuf,0,0,False);
3398 START_PROFILE(SMBtdis);
3400 vuid = SVAL(inbuf,smb_uid);
3403 DEBUG(4,("Invalid connection in tdis\n"));
3404 END_PROFILE(SMBtdis);
3405 return ERROR_DOS(ERRSRV,ERRinvnid);
3410 close_cnum(conn,vuid);
3412 END_PROFILE(SMBtdis);
3416 /****************************************************************************
3418 conn POINTER CAN BE NULL HERE !
3419 ****************************************************************************/
3421 int reply_echo(connection_struct *conn,
3422 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3424 int smb_reverb = SVAL(inbuf,smb_vwv0);
3426 unsigned int data_len = smb_buflen(inbuf);
3427 int outsize = set_message(outbuf,1,data_len,True);
3428 START_PROFILE(SMBecho);
3430 if (data_len > BUFFER_SIZE) {
3431 DEBUG(0,("reply_echo: data_len too large.\n"));
3432 END_PROFILE(SMBecho);
3436 /* copy any incoming data back out */
3438 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3440 if (smb_reverb > 100) {
3441 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3445 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3446 SSVAL(outbuf,smb_vwv0,seq_num);
3448 smb_setlen(outbuf,outsize - 4);
3451 if (!send_smb(smbd_server_fd(),outbuf))
3452 exit_server_cleanly("reply_echo: send_smb failed.");
3455 DEBUG(3,("echo %d times\n", smb_reverb));
3459 END_PROFILE(SMBecho);
3463 /****************************************************************************
3464 Reply to a printopen.
3465 ****************************************************************************/
3467 int reply_printopen(connection_struct *conn,
3468 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3474 START_PROFILE(SMBsplopen);
3476 if (!CAN_PRINT(conn)) {
3477 END_PROFILE(SMBsplopen);
3478 return ERROR_DOS(ERRDOS,ERRnoaccess);
3481 /* Open for exclusive use, write only. */
3482 status = print_fsp_open(conn, NULL, &fsp);
3484 if (!NT_STATUS_IS_OK(status)) {
3485 END_PROFILE(SMBsplopen);
3486 return(ERROR_NT(status));
3489 outsize = set_message(outbuf,1,0,True);
3490 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3492 DEBUG(3,("openprint fd=%d fnum=%d\n",
3493 fsp->fh->fd, fsp->fnum));
3495 END_PROFILE(SMBsplopen);
3499 /****************************************************************************
3500 Reply to a printclose.
3501 ****************************************************************************/
3503 int reply_printclose(connection_struct *conn,
3504 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3506 int outsize = set_message(outbuf,0,0,False);
3507 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3509 START_PROFILE(SMBsplclose);
3511 CHECK_FSP(fsp,conn);
3513 if (!CAN_PRINT(conn)) {
3514 END_PROFILE(SMBsplclose);
3515 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3518 DEBUG(3,("printclose fd=%d fnum=%d\n",
3519 fsp->fh->fd,fsp->fnum));
3521 status = close_file(fsp,NORMAL_CLOSE);
3523 if(!NT_STATUS_IS_OK(status)) {
3524 END_PROFILE(SMBsplclose);
3525 return ERROR_NT(status);
3528 END_PROFILE(SMBsplclose);
3532 /****************************************************************************
3533 Reply to a printqueue.
3534 ****************************************************************************/
3536 int reply_printqueue(connection_struct *conn,
3537 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3539 int outsize = set_message(outbuf,2,3,True);
3540 int max_count = SVAL(inbuf,smb_vwv0);
3541 int start_index = SVAL(inbuf,smb_vwv1);
3542 START_PROFILE(SMBsplretq);
3544 /* we used to allow the client to get the cnum wrong, but that
3545 is really quite gross and only worked when there was only
3546 one printer - I think we should now only accept it if they
3547 get it right (tridge) */
3548 if (!CAN_PRINT(conn)) {
3549 END_PROFILE(SMBsplretq);
3550 return ERROR_DOS(ERRDOS,ERRnoaccess);
3553 SSVAL(outbuf,smb_vwv0,0);
3554 SSVAL(outbuf,smb_vwv1,0);
3555 SCVAL(smb_buf(outbuf),0,1);
3556 SSVAL(smb_buf(outbuf),1,0);
3558 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3559 start_index, max_count));
3562 print_queue_struct *queue = NULL;
3563 print_status_struct status;
3564 char *p = smb_buf(outbuf) + 3;
3565 int count = print_queue_status(SNUM(conn), &queue, &status);
3566 int num_to_get = ABS(max_count);
3567 int first = (max_count>0?start_index:start_index+max_count+1);
3573 num_to_get = MIN(num_to_get,count-first);
3576 for (i=first;i<first+num_to_get;i++) {
3577 srv_put_dos_date2(p,0,queue[i].time);
3578 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3579 SSVAL(p,5, queue[i].job);
3580 SIVAL(p,7,queue[i].size);
3582 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3587 outsize = set_message(outbuf,2,28*count+3,False);
3588 SSVAL(outbuf,smb_vwv0,count);
3589 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3590 SCVAL(smb_buf(outbuf),0,1);
3591 SSVAL(smb_buf(outbuf),1,28*count);
3596 DEBUG(3,("%d entries returned in queue\n",count));
3599 END_PROFILE(SMBsplretq);
3603 /****************************************************************************
3604 Reply to a printwrite.
3605 ****************************************************************************/
3607 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3610 int outsize = set_message(outbuf,0,0,False);
3612 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3614 START_PROFILE(SMBsplwr);
3616 if (!CAN_PRINT(conn)) {
3617 END_PROFILE(SMBsplwr);
3618 return ERROR_DOS(ERRDOS,ERRnoaccess);
3621 CHECK_FSP(fsp,conn);
3622 if (!CHECK_WRITE(fsp)) {
3623 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3626 numtowrite = SVAL(smb_buf(inbuf),1);
3627 data = smb_buf(inbuf) + 3;
3629 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3630 END_PROFILE(SMBsplwr);
3631 return(UNIXERROR(ERRHRD,ERRdiskfull));
3634 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3636 END_PROFILE(SMBsplwr);
3640 /****************************************************************************
3642 ****************************************************************************/
3644 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3649 SMB_STRUCT_STAT sbuf;
3651 START_PROFILE(SMBmkdir);
3653 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3654 if (!NT_STATUS_IS_OK(status)) {
3655 END_PROFILE(SMBmkdir);
3656 return ERROR_NT(status);
3659 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) {
3660 END_PROFILE(SMBmkdir);
3661 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3664 status = unix_convert(conn, directory, False, NULL, &sbuf);
3665 if (!NT_STATUS_IS_OK(status)) {
3666 END_PROFILE(SMBmkdir);
3667 return ERROR_NT(status);
3670 status = check_name(conn, directory);
3671 if (!NT_STATUS_IS_OK(status)) {
3672 END_PROFILE(SMBmkdir);
3673 return ERROR_NT(status);
3676 status = create_directory(conn, directory);
3678 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3680 if (!NT_STATUS_IS_OK(status)) {
3682 if (!use_nt_status()
3683 && NT_STATUS_EQUAL(status,
3684 NT_STATUS_OBJECT_NAME_COLLISION)) {
3686 * Yes, in the DOS error code case we get a
3687 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3688 * samba4 torture test.
3690 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3693 END_PROFILE(SMBmkdir);
3694 return ERROR_NT(status);
3697 outsize = set_message(outbuf,0,0,False);
3699 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3701 END_PROFILE(SMBmkdir);
3705 /****************************************************************************
3706 Static function used by reply_rmdir to delete an entire directory
3707 tree recursively. Return True on ok, False on fail.
3708 ****************************************************************************/
3710 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3712 const char *dname = NULL;
3715 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3720 while((dname = ReadDirName(dir_hnd, &offset))) {
3724 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3727 if (!is_visible_file(conn, directory, dname, &st, False))
3730 /* Construct the full name. */
3731 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3737 pstrcpy(fullname, directory);
3738 pstrcat(fullname, "/");
3739 pstrcat(fullname, dname);
3741 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3746 if(st.st_mode & S_IFDIR) {
3747 if(!recursive_rmdir(conn, fullname)) {
3751 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3755 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3764 /****************************************************************************
3765 The internals of the rmdir code - called elsewhere.
3766 ****************************************************************************/
3768 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3773 ret = SMB_VFS_RMDIR(conn,directory);
3775 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3776 FILE_NOTIFY_CHANGE_DIR_NAME,
3778 return NT_STATUS_OK;
3781 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3783 * Check to see if the only thing in this directory are
3784 * vetoed files/directories. If so then delete them and
3785 * retry. If we fail to delete any of them (and we *don't*
3786 * do a recursive delete) then fail the rmdir.
3790 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3792 if(dir_hnd == NULL) {
3797 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3798 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3800 if (!is_visible_file(conn, directory, dname, &st, False))
3802 if(!IS_VETO_PATH(conn, dname)) {
3809 /* We only have veto files/directories. Recursive delete. */
3811 RewindDir(dir_hnd,&dirpos);
3812 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3815 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3817 if (!is_visible_file(conn, directory, dname, &st, False))
3820 /* Construct the full name. */
3821 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3826 pstrcpy(fullname, directory);
3827 pstrcat(fullname, "/");
3828 pstrcat(fullname, dname);
3830 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3832 if(st.st_mode & S_IFDIR) {
3833 if(lp_recursive_veto_delete(SNUM(conn))) {
3834 if(!recursive_rmdir(conn, fullname))
3837 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3839 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3843 /* Retry the rmdir */
3844 ret = SMB_VFS_RMDIR(conn,directory);
3850 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3851 "%s\n", directory,strerror(errno)));
3852 return map_nt_error_from_unix(errno);
3855 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3856 FILE_NOTIFY_CHANGE_DIR_NAME,
3859 return NT_STATUS_OK;
3862 /****************************************************************************
3864 ****************************************************************************/
3866 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3870 SMB_STRUCT_STAT sbuf;
3872 START_PROFILE(SMBrmdir);
3874 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3875 if (!NT_STATUS_IS_OK(status)) {
3876 END_PROFILE(SMBrmdir);
3877 return ERROR_NT(status);
3880 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) {
3881 END_PROFILE(SMBrmdir);
3882 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3885 status = unix_convert(conn, directory, False, NULL, &sbuf);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 END_PROFILE(SMBrmdir);
3888 return ERROR_NT(status);
3891 status = check_name(conn, directory);
3892 if (!NT_STATUS_IS_OK(status)) {
3893 END_PROFILE(SMBrmdir);
3894 return ERROR_NT(status);
3897 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3898 status = rmdir_internals(conn, directory);
3899 if (!NT_STATUS_IS_OK(status)) {
3900 END_PROFILE(SMBrmdir);
3901 return ERROR_NT(status);
3904 outsize = set_message(outbuf,0,0,False);
3906 DEBUG( 3, ( "rmdir %s\n", directory ) );
3908 END_PROFILE(SMBrmdir);
3912 /*******************************************************************
3913 Resolve wildcards in a filename rename.
3914 Note that name is in UNIX charset and thus potentially can be more
3915 than fstring buffer (255 bytes) especially in default UTF-8 case.
3916 Therefore, we use pstring inside and all calls should ensure that
3917 name2 is at least pstring-long (they do already)
3918 ********************************************************************/
3920 static BOOL resolve_wildcards(const char *name1, char *name2)
3922 pstring root1,root2;
3924 char *p,*p2, *pname1, *pname2;
3925 int available_space, actual_space;
3927 pname1 = strrchr_m(name1,'/');
3928 pname2 = strrchr_m(name2,'/');
3930 if (!pname1 || !pname2)
3933 pstrcpy(root1,pname1);
3934 pstrcpy(root2,pname2);
3935 p = strrchr_m(root1,'.');
3942 p = strrchr_m(root2,'.');
3956 } else if (*p2 == '*') {
3972 } else if (*p2 == '*') {
3982 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3985 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3986 if (actual_space >= available_space - 1) {
3987 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3988 actual_space - available_space));
3991 pstrcpy_base(pname2, root2, name2);
3997 /****************************************************************************
3998 Ensure open files have their names updated. Updated to notify other smbd's
4000 ****************************************************************************/
4002 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4003 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4006 BOOL did_rename = False;
4008 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4009 /* fsp_name is a relative path under the fsp. To change this for other
4010 sharepaths we need to manipulate relative paths. */
4011 /* TODO - create the absolute path and manipulate the newname
4012 relative to the sharepath. */
4013 if (fsp->conn != conn) {
4016 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4017 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4018 fsp->fsp_name, newname ));
4019 string_set(&fsp->fsp_name, newname);
4024 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4025 (unsigned int)dev, (double)inode, newname ));
4028 /* Send messages to all smbd's (not ourself) that the name has changed. */
4029 rename_share_filename(lck, conn->connectpath, newname);
4032 /****************************************************************************
4033 We need to check if the source path is a parent directory of the destination
4034 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4035 refuse the rename with a sharing violation. Under UNIX the above call can
4036 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4037 probably need to check that the client is a Windows one before disallowing
4038 this as a UNIX client (one with UNIX extensions) can know the source is a
4039 symlink and make this decision intelligently. Found by an excellent bug
4040 report from <AndyLiebman@aol.com>.
4041 ****************************************************************************/
4043 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4045 const char *psrc = src;
4046 const char *pdst = dest;
4049 if (psrc[0] == '.' && psrc[1] == '/') {
4052 if (pdst[0] == '.' && pdst[1] == '/') {
4055 if ((slen = strlen(psrc)) > strlen(pdst)) {
4058 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4061 /****************************************************************************
4062 Rename an open file - given an fsp.
4063 ****************************************************************************/
4065 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4067 SMB_STRUCT_STAT sbuf;
4068 pstring newname_last_component;
4069 NTSTATUS status = NT_STATUS_OK;
4071 struct share_mode_lock *lck = NULL;
4075 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4076 if (!NT_STATUS_IS_OK(status)) {
4080 status = check_name(conn, newname);
4081 if (!NT_STATUS_IS_OK(status)) {
4085 /* Ensure newname contains a '/' */
4086 if(strrchr_m(newname,'/') == 0) {
4089 pstrcpy(tmpstr, "./");
4090 pstrcat(tmpstr, newname);
4091 pstrcpy(newname, tmpstr);
4095 * Check for special case with case preserving and not
4096 * case sensitive. If the old last component differs from the original
4097 * last component only by case, then we should allow
4098 * the rename (user is trying to change the case of the
4102 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4103 strequal(newname, fsp->fsp_name)) {
4105 pstring newname_modified_last_component;
4108 * Get the last component of the modified name.
4109 * Note that we guarantee that newname contains a '/'
4112 p = strrchr_m(newname,'/');
4113 pstrcpy(newname_modified_last_component,p+1);
4115 if(strcsequal(newname_modified_last_component,
4116 newname_last_component) == False) {
4118 * Replace the modified last component with
4121 pstrcpy(p+1, newname_last_component);
4126 * If the src and dest names are identical - including case,
4127 * don't do the rename, just return success.
4130 if (strcsequal(fsp->fsp_name, newname)) {
4131 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4133 return NT_STATUS_OK;
4136 dest_exists = vfs_object_exist(conn,newname,NULL);
4138 if(!replace_if_exists && dest_exists) {
4139 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4140 fsp->fsp_name,newname));
4141 return NT_STATUS_OBJECT_NAME_COLLISION;
4144 status = can_rename(conn,newname,attrs,&sbuf);
4146 if (dest_exists && !NT_STATUS_IS_OK(status)) {
4147 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4148 nt_errstr(status), fsp->fsp_name,newname));
4149 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4150 status = NT_STATUS_ACCESS_DENIED;
4154 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4155 return NT_STATUS_ACCESS_DENIED;
4158 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4160 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4161 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4162 fsp->fsp_name,newname));
4163 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4165 return NT_STATUS_OK;
4170 if (errno == ENOTDIR || errno == EISDIR) {
4171 status = NT_STATUS_OBJECT_NAME_COLLISION;
4173 status = map_nt_error_from_unix(errno);
4176 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4177 nt_errstr(status), fsp->fsp_name,newname));
4183 * Do the notify calls from a rename
4186 static void notify_rename(connection_struct *conn, BOOL is_dir,
4187 const char *oldpath, const char *newpath)
4189 char *olddir, *newdir;
4190 const char *oldname, *newname;
4193 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4194 : FILE_NOTIFY_CHANGE_FILE_NAME;
4196 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4197 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4198 TALLOC_FREE(olddir);
4202 if (strcmp(olddir, newdir) == 0) {
4203 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4204 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4207 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4208 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4210 TALLOC_FREE(olddir);
4211 TALLOC_FREE(newdir);
4213 /* this is a strange one. w2k3 gives an additional event for
4214 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4215 files, but not directories */
4217 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4218 FILE_NOTIFY_CHANGE_ATTRIBUTES
4219 |FILE_NOTIFY_CHANGE_CREATION,
4224 /****************************************************************************
4225 The guts of the rename command, split out so it may be called by the NT SMB
4227 ****************************************************************************/
4229 NTSTATUS rename_internals(connection_struct *conn,
4233 BOOL replace_if_exists,
4239 pstring last_component_src;
4240 pstring last_component_dest;
4243 NTSTATUS status = NT_STATUS_OK;
4244 SMB_STRUCT_STAT sbuf1, sbuf2;
4245 struct share_mode_lock *lck = NULL;
4246 struct smb_Dir *dir_hnd = NULL;
4251 *directory = *mask = 0;
4256 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4257 if (!NT_STATUS_IS_OK(status)) {
4261 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4262 if (!NT_STATUS_IS_OK(status)) {
4267 * Split the old name into directory and last component
4268 * strings. Note that unix_convert may have stripped off a
4269 * leading ./ from both name and newname if the rename is
4270 * at the root of the share. We need to make sure either both
4271 * name and newname contain a / character or neither of them do
4272 * as this is checked in resolve_wildcards().
4275 p = strrchr_m(name,'/');
4277 pstrcpy(directory,".");
4281 pstrcpy(directory,name);
4283 *p = '/'; /* Replace needed for exceptional test below. */
4287 * We should only check the mangled cache
4288 * here if unix_convert failed. This means
4289 * that the path in 'mask' doesn't exist
4290 * on the file system and so we need to look
4291 * for a possible mangle. This patch from
4292 * Tine Smukavec <valentin.smukavec@hermes.si>.
4295 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4296 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4299 if (!src_has_wild) {
4301 * No wildcards - just process the one file.
4303 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4305 /* Add a terminating '/' to the directory name. */
4306 pstrcat(directory,"/");
4307 pstrcat(directory,mask);
4309 /* Ensure newname contains a '/' also */
4310 if(strrchr_m(newname,'/') == 0) {
4313 pstrcpy(tmpstr, "./");
4314 pstrcat(tmpstr, newname);
4315 pstrcpy(newname, tmpstr);
4318 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4319 "case_preserve = %d, short case preserve = %d, "
4320 "directory = %s, newname = %s, "
4321 "last_component_dest = %s, is_8_3 = %d\n",
4322 conn->case_sensitive, conn->case_preserve,
4323 conn->short_case_preserve, directory,
4324 newname, last_component_dest, is_short_name));
4326 /* Ensure the source name is valid for us to access. */
4327 status = check_name(conn, directory);
4328 if (!NT_STATUS_IS_OK(status)) {
4332 /* The dest name still may have wildcards. */
4333 if (dest_has_wild) {
4334 if (!resolve_wildcards(directory,newname)) {
4335 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4336 directory,newname));
4337 return NT_STATUS_NO_MEMORY;
4342 * Check for special case with case preserving and not
4343 * case sensitive, if directory and newname are identical,
4344 * and the old last component differs from the original
4345 * last component only by case, then we should allow
4346 * the rename (user is trying to change the case of the
4349 if((conn->case_sensitive == False) &&
4350 (((conn->case_preserve == True) &&
4351 (is_short_name == False)) ||
4352 ((conn->short_case_preserve == True) &&
4353 (is_short_name == True))) &&
4354 strcsequal(directory, newname)) {
4355 pstring modified_last_component;
4358 * Get the last component of the modified name.
4359 * Note that we guarantee that newname contains a '/'
4362 p = strrchr_m(newname,'/');
4363 pstrcpy(modified_last_component,p+1);
4365 if(strcsequal(modified_last_component,
4366 last_component_dest) == False) {
4368 * Replace the modified last component with
4371 pstrcpy(p+1, last_component_dest);
4375 /* Ensure the dest name is valid for us to access. */
4376 status = check_name(conn, newname);
4377 if (!NT_STATUS_IS_OK(status)) {
4382 * The source object must exist.
4385 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4386 DEBUG(3, ("rename_internals: source doesn't exist "
4387 "doing rename %s -> %s\n",
4388 directory,newname));
4390 if (errno == ENOTDIR || errno == EISDIR
4391 || errno == ENOENT) {
4393 * Must return different errors depending on
4394 * whether the parent directory existed or
4398 p = strrchr_m(directory, '/');
4400 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4402 if (vfs_object_exist(conn, directory, NULL))
4403 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4404 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4406 status = map_nt_error_from_unix(errno);
4407 DEBUG(3, ("rename_internals: Error %s rename %s -> "
4408 "%s\n", nt_errstr(status), directory,
4414 status = can_rename(conn,directory,attrs,&sbuf1);
4416 if (!NT_STATUS_IS_OK(status)) {
4417 DEBUG(3,("rename_internals: Error %s rename %s -> "
4418 "%s\n", nt_errstr(status), directory,
4424 * If the src and dest names are identical - including case,
4425 * don't do the rename, just return success.
4428 if (strcsequal(directory, newname)) {
4429 rename_open_files(conn, NULL, sbuf1.st_dev,
4430 sbuf1.st_ino, newname);
4431 DEBUG(3, ("rename_internals: identical names in "
4432 "rename %s - returning success\n",
4434 return NT_STATUS_OK;
4437 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4438 DEBUG(3,("rename_internals: dest exists doing "
4439 "rename %s -> %s\n", directory, newname));
4440 return NT_STATUS_OBJECT_NAME_COLLISION;
4443 if (rename_path_prefix_equal(directory, newname)) {
4444 return NT_STATUS_SHARING_VIOLATION;
4447 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4450 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4451 DEBUG(3,("rename_internals: succeeded doing rename "
4452 "on %s -> %s\n", directory, newname));
4453 rename_open_files(conn, lck, sbuf1.st_dev,
4454 sbuf1.st_ino, newname);
4456 notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4457 directory, newname);
4458 return NT_STATUS_OK;
4462 if (errno == ENOTDIR || errno == EISDIR) {
4463 status = NT_STATUS_OBJECT_NAME_COLLISION;
4465 status = map_nt_error_from_unix(errno);
4468 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4469 nt_errstr(status), directory,newname));
4475 * Wildcards - process each file that matches.
4477 if (strequal(mask,"????????.???")) {
4481 status = check_name(conn, directory);
4482 if (!NT_STATUS_IS_OK(status)) {
4486 dir_hnd = OpenDir(conn, directory, mask, attrs);
4487 if (dir_hnd == NULL) {
4488 return map_nt_error_from_unix(errno);
4491 status = NT_STATUS_NO_SUCH_FILE;
4493 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4494 * - gentest fix. JRA
4497 while ((dname = ReadDirName(dir_hnd, &offset))) {
4499 BOOL sysdir_entry = False;
4501 pstrcpy(fname,dname);
4503 /* Quick check for "." and ".." */
4504 if (fname[0] == '.') {
4505 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4507 sysdir_entry = True;
4514 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4518 if(!mask_match(fname, mask, conn->case_sensitive)) {
4523 status = NT_STATUS_OBJECT_NAME_INVALID;
4527 status = NT_STATUS_ACCESS_DENIED;
4528 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4530 /* Ensure the source name is valid for us to access. */
4531 status = check_name(conn, fname);
4532 if (!NT_STATUS_IS_OK(status)) {
4536 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4537 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4538 DEBUG(6, ("rename %s failed. Error %s\n",
4539 fname, nt_errstr(status)));
4542 status = can_rename(conn,fname,attrs,&sbuf1);
4543 if (!NT_STATUS_IS_OK(status)) {
4544 DEBUG(6, ("rename %s refused\n", fname));
4547 pstrcpy(destname,newname);
4549 if (!resolve_wildcards(fname,destname)) {
4550 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4555 /* Ensure the dest name is valid for us to access. */
4556 status = check_name(conn, destname);
4557 if (!NT_STATUS_IS_OK(status)) {
4561 if (strcsequal(fname,destname)) {
4562 rename_open_files(conn, NULL, sbuf1.st_dev,
4563 sbuf1.st_ino, newname);
4564 DEBUG(3,("rename_internals: identical names "
4565 "in wildcard rename %s - success\n",
4568 status = NT_STATUS_OK;
4572 if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
4573 DEBUG(6,("file_exist %s\n", destname));
4574 status = NT_STATUS_OBJECT_NAME_COLLISION;
4578 if (rename_path_prefix_equal(fname, destname)) {
4579 return NT_STATUS_SHARING_VIOLATION;
4582 lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4583 sbuf1.st_ino, NULL, NULL);
4585 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4586 rename_open_files(conn, lck, sbuf1.st_dev,
4587 sbuf1.st_ino, newname);
4589 status = NT_STATUS_OK;
4592 DEBUG(3,("rename_internals: doing rename on %s -> "
4593 "%s\n",fname,destname));
4597 if (count == 0 && NT_STATUS_IS_OK(status)) {
4598 status = map_nt_error_from_unix(errno);
4604 /****************************************************************************
4606 ****************************************************************************/
4608 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4615 uint32 attrs = SVAL(inbuf,smb_vwv0);
4617 BOOL src_has_wcard = False;
4618 BOOL dest_has_wcard = False;
4620 START_PROFILE(SMBmv);
4622 p = smb_buf(inbuf) + 1;
4623 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
4624 if (!NT_STATUS_IS_OK(status)) {
4626 return ERROR_NT(status);
4629 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
4630 if (!NT_STATUS_IS_OK(status)) {
4632 return ERROR_NT(status);
4635 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
4637 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4639 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) {
4641 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4644 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4646 status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
4647 if (!NT_STATUS_IS_OK(status)) {
4649 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4650 /* We have re-scheduled this call. */
4653 return ERROR_NT(status);
4656 outsize = set_message(outbuf,0,0,False);
4662 /*******************************************************************
4663 Copy a file as part of a reply_copy.
4664 ******************************************************************/
4667 * TODO: check error codes on all callers
4670 NTSTATUS copy_file(connection_struct *conn,
4675 BOOL target_is_directory)
4677 SMB_STRUCT_STAT src_sbuf, sbuf2;
4679 files_struct *fsp1,*fsp2;
4682 uint32 new_create_disposition;
4685 pstrcpy(dest,dest1);
4686 if (target_is_directory) {
4687 char *p = strrchr_m(src,'/');
4697 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4698 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4701 if (!target_is_directory && count) {
4702 new_create_disposition = FILE_OPEN;
4704 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4705 NULL, NULL, &new_create_disposition, NULL)) {
4706 return NT_STATUS_INVALID_PARAMETER;
4710 status = open_file_ntcreate(conn,src,&src_sbuf,
4712 FILE_SHARE_READ|FILE_SHARE_WRITE,
4715 FILE_ATTRIBUTE_NORMAL,
4719 if (!NT_STATUS_IS_OK(status)) {
4723 dosattrs = dos_mode(conn, src, &src_sbuf);
4724 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4725 ZERO_STRUCTP(&sbuf2);
4728 status = open_file_ntcreate(conn,dest,&sbuf2,
4730 FILE_SHARE_READ|FILE_SHARE_WRITE,
4731 new_create_disposition,
4737 if (!NT_STATUS_IS_OK(status)) {
4738 close_file(fsp1,ERROR_CLOSE);
4742 if ((ofun&3) == 1) {
4743 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4744 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4746 * Stop the copy from occurring.
4749 src_sbuf.st_size = 0;
4753 if (src_sbuf.st_size) {
4754 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4757 close_file(fsp1,NORMAL_CLOSE);
4759 /* Ensure the modtime is set correctly on the destination file. */
4760 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4763 * As we are opening fsp1 read-only we only expect
4764 * an error on close on fsp2 if we are out of space.
4765 * Thus we don't look at the error return from the
4768 status = close_file(fsp2,NORMAL_CLOSE);
4770 if (!NT_STATUS_IS_OK(status)) {
4774 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4775 return NT_STATUS_DISK_FULL;
4778 return NT_STATUS_OK;
4781 /****************************************************************************
4782 Reply to a file copy.
4783 ****************************************************************************/
4785 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4790 pstring mask,newname;
4793 int error = ERRnoaccess;
4795 int tid2 = SVAL(inbuf,smb_vwv0);
4796 int ofun = SVAL(inbuf,smb_vwv1);
4797 int flags = SVAL(inbuf,smb_vwv2);
4798 BOOL target_is_directory=False;
4799 BOOL source_has_wild = False;
4800 BOOL dest_has_wild = False;
4801 SMB_STRUCT_STAT sbuf1, sbuf2;
4803 START_PROFILE(SMBcopy);
4805 *directory = *mask = 0;
4808 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
4809 if (!NT_STATUS_IS_OK(status)) {
4810 END_PROFILE(SMBcopy);
4811 return ERROR_NT(status);
4813 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
4814 if (!NT_STATUS_IS_OK(status)) {
4815 END_PROFILE(SMBcopy);
4816 return ERROR_NT(status);
4819 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4821 if (tid2 != conn->cnum) {
4822 /* can't currently handle inter share copies XXXX */
4823 DEBUG(3,("Rejecting inter-share copy\n"));
4824 END_PROFILE(SMBcopy);
4825 return ERROR_DOS(ERRSRV,ERRinvdevice);
4828 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
4829 END_PROFILE(SMBcopy);
4830 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4832 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) {
4833 END_PROFILE(SMBcopy);
4834 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4837 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
4838 if (!NT_STATUS_IS_OK(status)) {
4839 END_PROFILE(SMBcopy);
4840 return ERROR_NT(status);
4843 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
4844 if (!NT_STATUS_IS_OK(status)) {
4845 END_PROFILE(SMBcopy);
4846 return ERROR_NT(status);
4849 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4851 if ((flags&1) && target_is_directory) {
4852 END_PROFILE(SMBcopy);
4853 return ERROR_DOS(ERRDOS,ERRbadfile);
4856 if ((flags&2) && !target_is_directory) {
4857 END_PROFILE(SMBcopy);
4858 return ERROR_DOS(ERRDOS,ERRbadpath);
4861 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4862 /* wants a tree copy! XXXX */
4863 DEBUG(3,("Rejecting tree copy\n"));
4864 END_PROFILE(SMBcopy);
4865 return ERROR_DOS(ERRSRV,ERRerror);
4868 p = strrchr_m(name,'/');
4870 pstrcpy(directory,"./");
4874 pstrcpy(directory,name);
4879 * We should only check the mangled cache
4880 * here if unix_convert failed. This means
4881 * that the path in 'mask' doesn't exist
4882 * on the file system and so we need to look
4883 * for a possible mangle. This patch from
4884 * Tine Smukavec <valentin.smukavec@hermes.si>.
4887 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4888 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4891 if (!source_has_wild) {
4892 pstrcat(directory,"/");
4893 pstrcat(directory,mask);
4894 if (dest_has_wild) {
4895 if (!resolve_wildcards(directory,newname)) {
4896 END_PROFILE(SMBcopy);
4897 return ERROR_NT(NT_STATUS_NO_MEMORY);
4901 status = check_name(conn, directory);
4902 if (!NT_STATUS_IS_OK(status)) {
4903 return ERROR_NT(status);
4906 status = check_name(conn, newname);
4907 if (!NT_STATUS_IS_OK(status)) {
4908 return ERROR_NT(status);
4911 status = copy_file(conn,directory,newname,ofun,
4912 count,target_is_directory);
4914 if(!NT_STATUS_IS_OK(status)) {
4915 END_PROFILE(SMBcopy);
4916 return ERROR_NT(status);
4921 struct smb_Dir *dir_hnd = NULL;
4926 if (strequal(mask,"????????.???"))
4929 status = check_name(conn, directory);
4930 if (!NT_STATUS_IS_OK(status)) {
4931 return ERROR_NT(status);
4934 dir_hnd = OpenDir(conn, directory, mask, 0);
4935 if (dir_hnd == NULL) {
4936 status = map_nt_error_from_unix(errno);
4937 return ERROR_NT(status);
4942 while ((dname = ReadDirName(dir_hnd, &offset))) {
4944 pstrcpy(fname,dname);
4946 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4950 if(!mask_match(fname, mask, conn->case_sensitive)) {
4954 error = ERRnoaccess;
4955 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4956 pstrcpy(destname,newname);
4957 if (!resolve_wildcards(fname,destname)) {
4961 status = check_name(conn, fname);
4962 if (!NT_STATUS_IS_OK(status)) {
4963 return ERROR_NT(status);
4966 status = check_name(conn, destname);
4967 if (!NT_STATUS_IS_OK(status)) {
4968 return ERROR_NT(status);
4971 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
4973 status = copy_file(conn,fname,destname,ofun,
4974 count,target_is_directory);
4975 if (NT_STATUS_IS_OK(status)) {
4984 /* Error on close... */
4986 END_PROFILE(SMBcopy);
4987 return(UNIXERROR(ERRHRD,ERRgeneral));
4990 END_PROFILE(SMBcopy);
4991 return ERROR_DOS(ERRDOS,error);
4994 outsize = set_message(outbuf,1,0,True);
4995 SSVAL(outbuf,smb_vwv0,count);
4997 END_PROFILE(SMBcopy);
5001 /****************************************************************************
5003 ****************************************************************************/
5005 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5012 START_PROFILE(pathworks_setdir);
5015 if (!CAN_SETDIR(snum)) {
5016 END_PROFILE(pathworks_setdir);
5017 return ERROR_DOS(ERRDOS,ERRnoaccess);
5020 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 END_PROFILE(pathworks_setdir);
5023 return ERROR_NT(status);
5026 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir)) {
5027 END_PROFILE(pathworks_setdir);
5028 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5031 if (strlen(newdir) != 0) {
5032 if (!vfs_directory_exist(conn,newdir,NULL)) {
5033 END_PROFILE(pathworks_setdir);
5034 return ERROR_DOS(ERRDOS,ERRbadpath);
5036 set_conn_connectpath(conn,newdir);
5039 outsize = set_message(outbuf,0,0,False);
5040 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5042 DEBUG(3,("setdir %s\n", newdir));
5044 END_PROFILE(pathworks_setdir);
5049 #define DBGC_CLASS DBGC_LOCKING
5051 /****************************************************************************
5052 Get a lock pid, dealing with large count requests.
5053 ****************************************************************************/
5055 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5057 if(!large_file_format)
5058 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5060 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5063 /****************************************************************************
5064 Get a lock count, dealing with large count requests.
5065 ****************************************************************************/
5067 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5069 SMB_BIG_UINT count = 0;
5071 if(!large_file_format) {
5072 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5075 #if defined(HAVE_LONGLONG)
5076 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5077 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5078 #else /* HAVE_LONGLONG */
5081 * NT4.x seems to be broken in that it sends large file (64 bit)
5082 * lockingX calls even if the CAP_LARGE_FILES was *not*
5083 * negotiated. For boxes without large unsigned ints truncate the
5084 * lock count by dropping the top 32 bits.
5087 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5088 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5089 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5090 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5091 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5094 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5095 #endif /* HAVE_LONGLONG */
5101 #if !defined(HAVE_LONGLONG)
5102 /****************************************************************************
5103 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5104 ****************************************************************************/
5106 static uint32 map_lock_offset(uint32 high, uint32 low)
5110 uint32 highcopy = high;
5113 * Try and find out how many significant bits there are in high.
5116 for(i = 0; highcopy; i++)
5120 * We use 31 bits not 32 here as POSIX
5121 * lock offsets may not be negative.
5124 mask = (~0) << (31 - i);
5127 return 0; /* Fail. */
5133 #endif /* !defined(HAVE_LONGLONG) */
5135 /****************************************************************************
5136 Get a lock offset, dealing with large offset requests.
5137 ****************************************************************************/
5139 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5141 SMB_BIG_UINT offset = 0;
5145 if(!large_file_format) {
5146 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5149 #if defined(HAVE_LONGLONG)
5150 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5151 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5152 #else /* HAVE_LONGLONG */
5155 * NT4.x seems to be broken in that it sends large file (64 bit)
5156 * lockingX calls even if the CAP_LARGE_FILES was *not*
5157 * negotiated. For boxes without large unsigned ints mangle the
5158 * lock offset by mapping the top 32 bits onto the lower 32.
5161 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5162 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5163 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5166 if((new_low = map_lock_offset(high, low)) == 0) {
5168 return (SMB_BIG_UINT)-1;
5171 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5172 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5173 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5174 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5177 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5178 #endif /* HAVE_LONGLONG */
5184 /****************************************************************************
5185 Reply to a lockingX request.
5186 ****************************************************************************/
5188 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5189 int length, int bufsize)
5191 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5192 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5193 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5194 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5195 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5196 SMB_BIG_UINT count = 0, offset = 0;
5198 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5201 BOOL large_file_format =
5202 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5204 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5206 START_PROFILE(SMBlockingX);
5208 CHECK_FSP(fsp,conn);
5210 data = smb_buf(inbuf);
5212 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5213 /* we don't support these - and CANCEL_LOCK makes w2k
5214 and XP reboot so I don't really want to be
5215 compatible! (tridge) */
5216 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5219 /* Check if this is an oplock break on a file
5220 we have granted an oplock on.
5222 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5223 /* Client can insist on breaking to none. */
5224 BOOL break_to_none = (oplocklevel == 0);
5227 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5228 "for fnum = %d\n", (unsigned int)oplocklevel,
5232 * Make sure we have granted an exclusive or batch oplock on
5236 if (fsp->oplock_type == 0) {
5238 /* The Samba4 nbench simulator doesn't understand
5239 the difference between break to level2 and break
5240 to none from level2 - it sends oplock break
5241 replies in both cases. Don't keep logging an error
5242 message here - just ignore it. JRA. */
5244 DEBUG(5,("reply_lockingX: Error : oplock break from "
5245 "client for fnum = %d (oplock=%d) and no "
5246 "oplock granted on this file (%s).\n",
5247 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5249 /* if this is a pure oplock break request then don't
5251 if (num_locks == 0 && num_ulocks == 0) {
5252 END_PROFILE(SMBlockingX);
5255 END_PROFILE(SMBlockingX);
5256 return ERROR_DOS(ERRDOS,ERRlock);
5260 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5262 result = remove_oplock(fsp);
5264 result = downgrade_oplock(fsp);
5268 DEBUG(0, ("reply_lockingX: error in removing "
5269 "oplock on file %s\n", fsp->fsp_name));
5270 /* Hmmm. Is this panic justified? */
5271 smb_panic("internal tdb error");
5274 reply_to_oplock_break_requests(fsp);
5276 /* if this is a pure oplock break request then don't send a
5278 if (num_locks == 0 && num_ulocks == 0) {
5279 /* Sanity check - ensure a pure oplock break is not a
5281 if(CVAL(inbuf,smb_vwv0) != 0xff)
5282 DEBUG(0,("reply_lockingX: Error : pure oplock "
5283 "break is a chained %d request !\n",
5284 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5285 END_PROFILE(SMBlockingX);
5291 * We do this check *after* we have checked this is not a oplock break
5292 * response message. JRA.
5295 release_level_2_oplocks_on_change(fsp);
5297 /* Data now points at the beginning of the list
5298 of smb_unlkrng structs */
5299 for(i = 0; i < (int)num_ulocks; i++) {
5300 lock_pid = get_lock_pid( data, i, large_file_format);
5301 count = get_lock_count( data, i, large_file_format);
5302 offset = get_lock_offset( data, i, large_file_format, &err);
5305 * There is no error code marked "stupid client bug".... :-).
5308 END_PROFILE(SMBlockingX);
5309 return ERROR_DOS(ERRDOS,ERRnoaccess);
5312 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5313 "pid %u, file %s\n", (double)offset, (double)count,
5314 (unsigned int)lock_pid, fsp->fsp_name ));
5316 status = do_unlock(fsp,
5322 if (NT_STATUS_V(status)) {
5323 END_PROFILE(SMBlockingX);
5324 return ERROR_NT(status);
5328 /* Setup the timeout in seconds. */
5330 if (!lp_blocking_locks(SNUM(conn))) {
5334 /* Now do any requested locks */
5335 data += ((large_file_format ? 20 : 10)*num_ulocks);
5337 /* Data now points at the beginning of the list
5338 of smb_lkrng structs */
5340 for(i = 0; i < (int)num_locks; i++) {
5341 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5342 READ_LOCK:WRITE_LOCK);
5343 lock_pid = get_lock_pid( data, i, large_file_format);
5344 count = get_lock_count( data, i, large_file_format);
5345 offset = get_lock_offset( data, i, large_file_format, &err);
5348 * There is no error code marked "stupid client bug".... :-).
5351 END_PROFILE(SMBlockingX);
5352 return ERROR_DOS(ERRDOS,ERRnoaccess);
5355 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5356 "%u, file %s timeout = %d\n", (double)offset,
5357 (double)count, (unsigned int)lock_pid,
5358 fsp->fsp_name, (int)lock_timeout ));
5360 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5361 if (lp_blocking_locks(SNUM(conn))) {
5363 /* Schedule a message to ourselves to
5364 remove the blocking lock record and
5365 return the right error. */
5367 if (!blocking_lock_cancel(fsp,
5373 NT_STATUS_FILE_LOCK_CONFLICT)) {
5374 END_PROFILE(SMBlockingX);
5375 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5378 /* Remove a matching pending lock. */
5379 status = do_lock_cancel(fsp,
5385 BOOL blocking_lock = lock_timeout ? True : False;
5386 BOOL defer_lock = False;
5387 struct byte_range_lock *br_lck;
5389 br_lck = do_lock(fsp,
5398 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5399 /* Windows internal resolution for blocking locks seems
5400 to be about 200ms... Don't wait for less than that. JRA. */
5401 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5402 lock_timeout = lp_lock_spin_time();
5407 /* This heuristic seems to match W2K3 very well. If a
5408 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5409 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5410 far as I can tell. Replacement for do_lock_spin(). JRA. */
5412 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5413 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5415 lock_timeout = lp_lock_spin_time();
5418 if (br_lck && defer_lock) {
5420 * A blocking lock was requested. Package up
5421 * this smb into a queued request and push it
5422 * onto the blocking lock queue.
5424 if(push_blocking_lock_request(br_lck,
5434 TALLOC_FREE(br_lck);
5435 END_PROFILE(SMBlockingX);
5440 TALLOC_FREE(br_lck);
5443 if (NT_STATUS_V(status)) {
5444 END_PROFILE(SMBlockingX);
5445 return ERROR_NT(status);
5449 /* If any of the above locks failed, then we must unlock
5450 all of the previous locks (X/Open spec). */
5452 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5456 * Ensure we don't do a remove on the lock that just failed,
5457 * as under POSIX rules, if we have a lock already there, we
5458 * will delete it (and we shouldn't) .....
5460 for(i--; i >= 0; i--) {
5461 lock_pid = get_lock_pid( data, i, large_file_format);
5462 count = get_lock_count( data, i, large_file_format);
5463 offset = get_lock_offset( data, i, large_file_format,
5467 * There is no error code marked "stupid client
5471 END_PROFILE(SMBlockingX);
5472 return ERROR_DOS(ERRDOS,ERRnoaccess);
5481 END_PROFILE(SMBlockingX);
5482 return ERROR_NT(status);
5485 set_message(outbuf,2,0,True);
5487 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5488 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5490 END_PROFILE(SMBlockingX);
5491 return chain_reply(inbuf,outbuf,length,bufsize);
5495 #define DBGC_CLASS DBGC_ALL
5497 /****************************************************************************
5498 Reply to a SMBreadbmpx (read block multiplex) request.
5499 ****************************************************************************/
5501 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5512 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5513 START_PROFILE(SMBreadBmpx);
5515 /* this function doesn't seem to work - disable by default */
5516 if (!lp_readbmpx()) {
5517 END_PROFILE(SMBreadBmpx);
5518 return ERROR_DOS(ERRSRV,ERRuseSTD);
5521 outsize = set_message(outbuf,8,0,True);
5523 CHECK_FSP(fsp,conn);
5524 if (!CHECK_READ(fsp,inbuf)) {
5525 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5528 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5529 maxcount = SVAL(inbuf,smb_vwv3);
5531 data = smb_buf(outbuf);
5532 pad = ((long)data)%4;
5537 max_per_packet = bufsize-(outsize+pad);
5541 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5542 END_PROFILE(SMBreadBmpx);
5543 return ERROR_DOS(ERRDOS,ERRlock);
5547 size_t N = MIN(max_per_packet,tcount-total_read);
5549 nread = read_file(fsp,data,startpos,N);
5554 if (nread < (ssize_t)N)
5555 tcount = total_read + nread;
5557 set_message(outbuf,8,nread+pad,False);
5558 SIVAL(outbuf,smb_vwv0,startpos);
5559 SSVAL(outbuf,smb_vwv2,tcount);
5560 SSVAL(outbuf,smb_vwv6,nread);
5561 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5564 if (!send_smb(smbd_server_fd(),outbuf))
5565 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5567 total_read += nread;
5569 } while (total_read < (ssize_t)tcount);
5571 END_PROFILE(SMBreadBmpx);
5575 /****************************************************************************
5576 Reply to a SMBsetattrE.
5577 ****************************************************************************/
5579 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5581 struct timespec ts[2];
5583 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5584 START_PROFILE(SMBsetattrE);
5586 outsize = set_message(outbuf,0,0,False);
5588 if(!fsp || (fsp->conn != conn)) {
5589 END_PROFILE(SMBsetattrE);
5590 return ERROR_DOS(ERRDOS,ERRbadfid);
5594 * Convert the DOS times into unix times. Ignore create
5595 * time as UNIX can't set this.
5598 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5599 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5602 * Patch from Ray Frush <frush@engr.colostate.edu>
5603 * Sometimes times are sent as zero - ignore them.
5606 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5607 /* Ignore request */
5608 if( DEBUGLVL( 3 ) ) {
5609 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5610 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5612 END_PROFILE(SMBsetattrE);
5614 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5615 /* set modify time = to access time if modify time was unset */
5619 /* Set the date on this file */
5620 /* Should we set pending modtime here ? JRA */
5621 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5622 END_PROFILE(SMBsetattrE);
5623 return ERROR_DOS(ERRDOS,ERRnoaccess);
5626 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5628 (unsigned int)ts[0].tv_sec,
5629 (unsigned int)ts[1].tv_sec));
5631 END_PROFILE(SMBsetattrE);
5636 /* Back from the dead for OS/2..... JRA. */
5638 /****************************************************************************
5639 Reply to a SMBwritebmpx (write block multiplex primary) request.
5640 ****************************************************************************/
5642 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5645 ssize_t nwritten = -1;
5652 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5653 START_PROFILE(SMBwriteBmpx);
5655 CHECK_FSP(fsp,conn);
5656 if (!CHECK_WRITE(fsp)) {
5657 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5659 if (HAS_CACHED_ERROR(fsp)) {
5660 return(CACHED_ERROR(fsp));
5663 tcount = SVAL(inbuf,smb_vwv1);
5664 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5665 write_through = BITSETW(inbuf+smb_vwv7,0);
5666 numtowrite = SVAL(inbuf,smb_vwv10);
5667 smb_doff = SVAL(inbuf,smb_vwv11);
5669 data = smb_base(inbuf) + smb_doff;
5671 /* If this fails we need to send an SMBwriteC response,
5672 not an SMBwritebmpx - set this up now so we don't forget */
5673 SCVAL(outbuf,smb_com,SMBwritec);
5675 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5676 END_PROFILE(SMBwriteBmpx);
5677 return(ERROR_DOS(ERRDOS,ERRlock));
5680 nwritten = write_file(fsp,data,startpos,numtowrite);
5682 sync_file(conn, fsp, write_through);
5684 if(nwritten < (ssize_t)numtowrite) {
5685 END_PROFILE(SMBwriteBmpx);
5686 return(UNIXERROR(ERRHRD,ERRdiskfull));
5689 /* If the maximum to be written to this file
5690 is greater than what we just wrote then set
5691 up a secondary struct to be attached to this
5692 fd, we will use this to cache error messages etc. */
5694 if((ssize_t)tcount > nwritten) {
5695 write_bmpx_struct *wbms;
5696 if(fsp->wbmpx_ptr != NULL)
5697 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5699 wbms = SMB_MALLOC_P(write_bmpx_struct);
5701 DEBUG(0,("Out of memory in reply_readmpx\n"));
5702 END_PROFILE(SMBwriteBmpx);
5703 return(ERROR_DOS(ERRSRV,ERRnoresource));
5705 wbms->wr_mode = write_through;
5706 wbms->wr_discard = False; /* No errors yet */
5707 wbms->wr_total_written = nwritten;
5708 wbms->wr_errclass = 0;
5710 fsp->wbmpx_ptr = wbms;
5713 /* We are returning successfully, set the message type back to
5715 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5717 outsize = set_message(outbuf,1,0,True);
5719 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5721 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5722 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5724 if (write_through && tcount==nwritten) {
5725 /* We need to send both a primary and a secondary response */
5726 smb_setlen(outbuf,outsize - 4);
5728 if (!send_smb(smbd_server_fd(),outbuf))
5729 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5731 /* Now the secondary */
5732 outsize = set_message(outbuf,1,0,True);
5733 SCVAL(outbuf,smb_com,SMBwritec);
5734 SSVAL(outbuf,smb_vwv0,nwritten);
5737 END_PROFILE(SMBwriteBmpx);
5741 /****************************************************************************
5742 Reply to a SMBwritebs (write block multiplex secondary) request.
5743 ****************************************************************************/
5745 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5748 ssize_t nwritten = -1;
5755 write_bmpx_struct *wbms;
5756 BOOL send_response = False;
5757 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5758 START_PROFILE(SMBwriteBs);
5760 CHECK_FSP(fsp,conn);
5761 if (!CHECK_WRITE(fsp)) {
5762 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5765 tcount = SVAL(inbuf,smb_vwv1);
5766 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5767 numtowrite = SVAL(inbuf,smb_vwv6);
5768 smb_doff = SVAL(inbuf,smb_vwv7);
5770 data = smb_base(inbuf) + smb_doff;
5772 /* We need to send an SMBwriteC response, not an SMBwritebs */
5773 SCVAL(outbuf,smb_com,SMBwritec);
5775 /* This fd should have an auxiliary struct attached,
5776 check that it does */
5777 wbms = fsp->wbmpx_ptr;
5779 END_PROFILE(SMBwriteBs);
5783 /* If write through is set we can return errors, else we must cache them */
5784 write_through = wbms->wr_mode;
5786 /* Check for an earlier error */
5787 if(wbms->wr_discard) {
5788 END_PROFILE(SMBwriteBs);
5789 return -1; /* Just discard the packet */
5792 nwritten = write_file(fsp,data,startpos,numtowrite);
5794 sync_file(conn, fsp, write_through);
5796 if (nwritten < (ssize_t)numtowrite) {
5798 /* We are returning an error - we can delete the aux struct */
5801 fsp->wbmpx_ptr = NULL;
5802 END_PROFILE(SMBwriteBs);
5803 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5805 wbms->wr_errclass = ERRHRD;
5806 wbms->wr_error = ERRdiskfull;
5807 wbms->wr_status = NT_STATUS_DISK_FULL;
5808 wbms->wr_discard = True;
5809 END_PROFILE(SMBwriteBs);
5813 /* Increment the total written, if this matches tcount
5814 we can discard the auxiliary struct (hurrah !) and return a writeC */
5815 wbms->wr_total_written += nwritten;
5816 if(wbms->wr_total_written >= tcount) {
5817 if (write_through) {
5818 outsize = set_message(outbuf,1,0,True);
5819 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5820 send_response = True;
5824 fsp->wbmpx_ptr = NULL;
5828 END_PROFILE(SMBwriteBs);
5832 END_PROFILE(SMBwriteBs);
5836 /****************************************************************************
5837 Reply to a SMBgetattrE.
5838 ****************************************************************************/
5840 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5842 SMB_STRUCT_STAT sbuf;
5845 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5846 START_PROFILE(SMBgetattrE);
5848 outsize = set_message(outbuf,11,0,True);
5850 if(!fsp || (fsp->conn != conn)) {
5851 END_PROFILE(SMBgetattrE);
5852 return ERROR_DOS(ERRDOS,ERRbadfid);
5855 /* Do an fstat on this file */
5856 if(fsp_stat(fsp, &sbuf)) {
5857 END_PROFILE(SMBgetattrE);
5858 return(UNIXERROR(ERRDOS,ERRnoaccess));
5861 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5864 * Convert the times into dos times. Set create
5865 * date to be last modify date as UNIX doesn't save
5869 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5870 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5871 /* Should we check pending modtime here ? JRA */
5872 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5875 SIVAL(outbuf,smb_vwv6,0);
5876 SIVAL(outbuf,smb_vwv8,0);
5878 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5879 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5880 SIVAL(outbuf,smb_vwv8,allocation_size);
5882 SSVAL(outbuf,smb_vwv10, mode);
5884 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5886 END_PROFILE(SMBgetattrE);