2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
33 extern char magic_char;
34 extern int global_oplock_break;
35 unsigned int smb_echo_count = 0;
36 extern uint32 global_client_caps;
38 extern BOOL global_encrypted_passwords_negotiated;
40 /****************************************************************************
41 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
50 const char *s = srcname;
51 NTSTATUS ret = NT_STATUS_OK;
52 BOOL start_of_name_component = True;
53 unsigned int num_bad_components = 0;
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
69 start_of_name_component = True;
73 if (start_of_name_component) {
74 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
75 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
78 * No mb char starts with '.' so we're safe checking the directory separator here.
81 /* If we just added a '/' - delete it */
82 if ((d > destname) && (*(d-1) == '/')) {
87 /* Are we at the start ? Can't go back further if so. */
89 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
92 /* Go back one level... */
93 /* We know this is safe as '/' cannot be part of a mb sequence. */
94 /* NOTE - if this assumption is invalid we are not in good shape... */
95 /* Decrement d first as d points to the *next* char to write into. */
96 for (d--; d > destname; d--) {
100 s += 2; /* Else go past the .. */
101 /* We're still at the start of a name component, just the previous one. */
103 if (num_bad_components) {
104 /* Hmmm. Should we only decrement the bad_components if
105 we're removing a bad component ? Need to check this. JRA. */
106 num_bad_components--;
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112 /* Component of pathname can't be "." only. */
113 ret = NT_STATUS_OBJECT_NAME_INVALID;
114 num_bad_components++;
127 return NT_STATUS_OBJECT_NAME_INVALID;
133 switch(next_mb_char_size(s)) {
144 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
146 return NT_STATUS_INVALID_PARAMETER;
149 if (start_of_name_component && num_bad_components) {
150 num_bad_components++;
152 start_of_name_component = False;
155 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
156 if (num_bad_components > 1) {
157 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
165 /****************************************************************************
166 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
167 path or anything including wildcards.
168 We're assuming here that '/' is not the second byte in any multibyte char
169 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
171 ****************************************************************************/
173 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
176 const char *s = srcname;
177 NTSTATUS ret = NT_STATUS_OK;
178 BOOL start_of_name_component = True;
179 unsigned int num_bad_components = 0;
182 if (IS_DIRECTORY_SEP(*s)) {
184 * Safe to assume is not the second part of a mb char as this is handled below.
186 /* Eat multiple '/' or '\\' */
187 while (IS_DIRECTORY_SEP(*s)) {
190 if ((d != destname) && (*s != '\0')) {
191 /* We only care about non-leading or trailing '/' or '\\' */
195 start_of_name_component = True;
199 if (start_of_name_component) {
200 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
201 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
204 * No mb char starts with '.' so we're safe checking the directory separator here.
207 /* If we just added a '/' - delete it */
208 if ((d > destname) && (*(d-1) == '/')) {
213 /* Are we at the start ? Can't go back further if so. */
215 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
218 /* Go back one level... */
219 /* We know this is safe as '/' cannot be part of a mb sequence. */
220 /* NOTE - if this assumption is invalid we are not in good shape... */
221 /* Decrement d first as d points to the *next* char to write into. */
222 for (d--; d > destname; d--) {
226 s += 2; /* Else go past the .. */
227 /* We're still at the start of a name component, just the previous one. */
229 if (num_bad_components) {
230 /* Hmmm. Should we only decrement the bad_components if
231 we're removing a bad component ? Need to check this. JRA. */
232 num_bad_components--;
237 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
238 /* Component of pathname can't be "." only. */
239 ret = NT_STATUS_OBJECT_NAME_INVALID;
240 num_bad_components++;
249 switch(next_mb_char_size(s)) {
260 DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
262 return NT_STATUS_INVALID_PARAMETER;
265 if (start_of_name_component && num_bad_components) {
266 num_bad_components++;
268 start_of_name_component = False;
271 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
272 /* For some strange reason being called from findfirst changes
273 the num_components number to cause the error return to change. JRA. */
274 if (num_bad_components > 2) {
275 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
283 /****************************************************************************
284 Pull a string and check the path - provide for error return.
285 ****************************************************************************/
287 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
290 char *tmppath_ptr = tmppath;
293 SMB_ASSERT(dest_len == sizeof(pstring));
297 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
299 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
301 if (allow_wcard_names) {
302 *err = check_path_syntax_wcard(dest, tmppath);
304 *err = check_path_syntax(dest, tmppath);
309 /****************************************************************************
310 Reply to a special message.
311 ****************************************************************************/
313 int reply_special(char *inbuf,char *outbuf)
316 int msg_type = CVAL(inbuf,0);
317 int msg_flags = CVAL(inbuf,1);
321 static BOOL already_got_session = False;
325 memset(outbuf,'\0',smb_size);
327 smb_setlen(outbuf,0);
330 case 0x81: /* session request */
332 if (already_got_session) {
333 exit_server("multiple session request not permitted");
336 SCVAL(outbuf,0,0x82);
338 if (name_len(inbuf+4) > 50 ||
339 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
340 DEBUG(0,("Invalid name length in session request\n"));
343 name_extract(inbuf,4,name1);
344 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
345 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
348 set_local_machine_name(name1, True);
349 set_remote_machine_name(name2, True);
351 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
352 get_local_machine_name(), get_remote_machine_name(),
355 if (name_type == 'R') {
356 /* We are being asked for a pathworks session ---
358 SCVAL(outbuf, 0,0x83);
362 /* only add the client's machine name to the list
363 of possibly valid usernames if we are operating
364 in share mode security */
365 if (lp_security() == SEC_SHARE) {
366 add_session_user(get_remote_machine_name());
369 reload_services(True);
372 already_got_session = True;
375 case 0x89: /* session keepalive request
376 (some old clients produce this?) */
377 SCVAL(outbuf,0,SMBkeepalive);
381 case 0x82: /* positive session response */
382 case 0x83: /* negative session response */
383 case 0x84: /* retarget session response */
384 DEBUG(0,("Unexpected session response\n"));
387 case SMBkeepalive: /* session keepalive */
392 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
393 msg_type, msg_flags));
398 /****************************************************************************
400 ****************************************************************************/
402 int reply_tcon(connection_struct *conn,
403 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
410 uint16 vuid = SVAL(inbuf,smb_uid);
414 DATA_BLOB password_blob;
416 START_PROFILE(SMBtcon);
418 *service_buf = *password = *dev = 0;
420 p = smb_buf(inbuf)+1;
421 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
422 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
424 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
426 p = strrchr_m(service_buf,'\\');
430 service = service_buf;
433 password_blob = data_blob(password, pwlen+1);
435 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
437 data_blob_clear_free(&password_blob);
440 END_PROFILE(SMBtcon);
441 return ERROR_NT(nt_status);
444 outsize = set_message(outbuf,2,0,True);
445 SSVAL(outbuf,smb_vwv0,max_recv);
446 SSVAL(outbuf,smb_vwv1,conn->cnum);
447 SSVAL(outbuf,smb_tid,conn->cnum);
449 DEBUG(3,("tcon service=%s cnum=%d\n",
450 service, conn->cnum));
452 END_PROFILE(SMBtcon);
456 /****************************************************************************
457 Reply to a tcon and X.
458 ****************************************************************************/
460 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
465 /* what the cleint thinks the device is */
466 fstring client_devicetype;
467 /* what the server tells the client the share represents */
468 const char *server_devicetype;
470 uint16 vuid = SVAL(inbuf,smb_uid);
471 int passlen = SVAL(inbuf,smb_vwv3);
474 extern BOOL global_encrypted_passwords_negotiated;
476 START_PROFILE(SMBtconX);
478 *service = *client_devicetype = 0;
480 /* we might have to close an old one */
481 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
482 close_cnum(conn,vuid);
485 if (passlen > MAX_PASS_LEN) {
486 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
489 if (global_encrypted_passwords_negotiated) {
490 password = data_blob(smb_buf(inbuf),passlen);
492 password = data_blob(smb_buf(inbuf),passlen+1);
493 /* Ensure correct termination */
494 password.data[passlen]=0;
497 p = smb_buf(inbuf) + passlen;
498 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
501 * the service name can be either: \\server\share
502 * or share directly like on the DELL PowerVault 705
505 q = strchr_m(path+2,'\\');
507 END_PROFILE(SMBtconX);
508 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
510 fstrcpy(service,q+1);
513 fstrcpy(service,path);
515 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
517 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
519 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
521 data_blob_clear_free(&password);
524 END_PROFILE(SMBtconX);
525 return ERROR_NT(nt_status);
529 server_devicetype = "IPC";
530 else if ( IS_PRINT(conn) )
531 server_devicetype = "LPT1:";
533 server_devicetype = "A:";
535 if (Protocol < PROTOCOL_NT1) {
536 set_message(outbuf,2,0,True);
538 p += srvstr_push(outbuf, p, server_devicetype, -1,
539 STR_TERMINATE|STR_ASCII);
540 set_message_end(outbuf,p);
542 /* NT sets the fstype of IPC$ to the null string */
543 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
545 set_message(outbuf,3,0,True);
548 p += srvstr_push(outbuf, p, server_devicetype, -1,
549 STR_TERMINATE|STR_ASCII);
550 p += srvstr_push(outbuf, p, fstype, -1,
553 set_message_end(outbuf,p);
555 /* what does setting this bit do? It is set by NT4 and
556 may affect the ability to autorun mounted cdroms */
557 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
558 (lp_csc_policy(SNUM(conn)) << 2));
560 init_dfsroot(conn, inbuf, outbuf);
564 DEBUG(3,("tconX service=%s \n",
567 /* set the incoming and outgoing tid to the just created one */
568 SSVAL(inbuf,smb_tid,conn->cnum);
569 SSVAL(outbuf,smb_tid,conn->cnum);
571 END_PROFILE(SMBtconX);
572 return chain_reply(inbuf,outbuf,length,bufsize);
575 /****************************************************************************
576 Reply to an unknown type.
577 ****************************************************************************/
579 int reply_unknown(char *inbuf,char *outbuf)
582 type = CVAL(inbuf,smb_com);
584 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
585 smb_fn_name(type), type, type));
587 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
590 /****************************************************************************
592 ****************************************************************************/
594 int reply_ioctl(connection_struct *conn,
595 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
597 uint16 device = SVAL(inbuf,smb_vwv1);
598 uint16 function = SVAL(inbuf,smb_vwv2);
599 uint32 ioctl_code = (device << 16) + function;
600 int replysize, outsize;
602 START_PROFILE(SMBioctl);
604 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
606 switch (ioctl_code) {
607 case IOCTL_QUERY_JOB_INFO:
611 END_PROFILE(SMBioctl);
612 return(ERROR_DOS(ERRSRV,ERRnosupport));
615 outsize = set_message(outbuf,8,replysize+1,True);
616 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
617 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
618 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
619 p = smb_buf(outbuf) + 1; /* Allow for alignment */
621 switch (ioctl_code) {
622 case IOCTL_QUERY_JOB_INFO:
624 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
626 END_PROFILE(SMBioctl);
627 return(UNIXERROR(ERRDOS,ERRbadfid));
629 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
630 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
632 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
638 END_PROFILE(SMBioctl);
642 /****************************************************************************
644 ****************************************************************************/
646 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
651 BOOL bad_path = False;
652 SMB_STRUCT_STAT sbuf;
655 START_PROFILE(SMBchkpth);
657 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
658 if (!NT_STATUS_IS_OK(status)) {
659 END_PROFILE(SMBchkpth);
660 return ERROR_NT(status);
663 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
665 unix_convert(name,conn,0,&bad_path,&sbuf);
667 END_PROFILE(SMBchkpth);
668 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
671 if (check_name(name,conn)) {
672 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
673 if (!(ok = S_ISDIR(sbuf.st_mode))) {
674 END_PROFILE(SMBchkpth);
675 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
680 /* We special case this - as when a Windows machine
681 is parsing a path is steps through the components
682 one at a time - if a component fails it expects
683 ERRbadpath, not ERRbadfile.
685 if(errno == ENOENT) {
687 * Windows returns different error codes if
688 * the parent directory is valid but not the
689 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
690 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
691 * if the path is invalid. This is different from set_bad_path_error()
692 * in the non-NT error case.
694 END_PROFILE(SMBchkpth);
695 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
698 END_PROFILE(SMBchkpth);
699 return(UNIXERROR(ERRDOS,ERRbadpath));
702 outsize = set_message(outbuf,0,0,True);
703 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
705 END_PROFILE(SMBchkpth);
709 /****************************************************************************
711 ****************************************************************************/
713 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
717 SMB_STRUCT_STAT sbuf;
722 BOOL bad_path = False;
726 START_PROFILE(SMBgetatr);
728 p = smb_buf(inbuf) + 1;
729 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
730 if (!NT_STATUS_IS_OK(status)) {
731 END_PROFILE(SMBgetatr);
732 return ERROR_NT(status);
735 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
737 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
738 under WfWg - weird! */
740 mode = aHIDDEN | aDIR;
741 if (!CAN_WRITE(conn))
747 unix_convert(fname,conn,0,&bad_path,&sbuf);
749 END_PROFILE(SMBgetatr);
750 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
752 if (check_name(fname,conn)) {
753 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
754 mode = dos_mode(conn,fname,&sbuf);
756 mtime = sbuf.st_mtime;
761 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
767 END_PROFILE(SMBgetatr);
768 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
771 outsize = set_message(outbuf,10,0,True);
773 SSVAL(outbuf,smb_vwv0,mode);
774 if(lp_dos_filetime_resolution(SNUM(conn)) )
775 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
777 put_dos_date3(outbuf,smb_vwv1,mtime);
778 SIVAL(outbuf,smb_vwv3,(uint32)size);
780 if (Protocol >= PROTOCOL_NT1)
781 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
783 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
785 END_PROFILE(SMBgetatr);
789 /****************************************************************************
791 ****************************************************************************/
793 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
800 SMB_STRUCT_STAT sbuf;
801 BOOL bad_path = False;
805 START_PROFILE(SMBsetatr);
807 p = smb_buf(inbuf) + 1;
808 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
809 if (!NT_STATUS_IS_OK(status)) {
810 END_PROFILE(SMBsetatr);
811 return ERROR_NT(status);
814 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
816 unix_convert(fname,conn,0,&bad_path,&sbuf);
818 END_PROFILE(SMBsetatr);
819 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
822 mode = SVAL(inbuf,smb_vwv0);
823 mtime = make_unix_date3(inbuf+smb_vwv1);
825 if (mode != FILE_ATTRIBUTE_NORMAL) {
826 if (VALID_STAT_OF_DIR(sbuf))
831 if (check_name(fname,conn)) {
832 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
839 ok = set_filetime(conn,fname,mtime);
842 END_PROFILE(SMBsetatr);
843 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
846 outsize = set_message(outbuf,0,0,True);
848 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
850 END_PROFILE(SMBsetatr);
854 /****************************************************************************
856 ****************************************************************************/
858 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
861 SMB_BIG_UINT dfree,dsize,bsize;
862 START_PROFILE(SMBdskattr);
864 if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
865 END_PROFILE(SMBdskattr);
866 return(UNIXERROR(ERRHRD,ERRgeneral));
869 outsize = set_message(outbuf,5,0,True);
871 if (Protocol <= PROTOCOL_LANMAN2) {
872 double total_space, free_space;
873 /* we need to scale this to a number that DOS6 can handle. We
874 use floating point so we can handle large drives on systems
875 that don't have 64 bit integers
877 we end up displaying a maximum of 2G to DOS systems
879 total_space = dsize * (double)bsize;
880 free_space = dfree * (double)bsize;
882 dsize = (total_space+63*512) / (64*512);
883 dfree = (free_space+63*512) / (64*512);
885 if (dsize > 0xFFFF) dsize = 0xFFFF;
886 if (dfree > 0xFFFF) dfree = 0xFFFF;
888 SSVAL(outbuf,smb_vwv0,dsize);
889 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
890 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
891 SSVAL(outbuf,smb_vwv3,dfree);
893 SSVAL(outbuf,smb_vwv0,dsize);
894 SSVAL(outbuf,smb_vwv1,bsize/512);
895 SSVAL(outbuf,smb_vwv2,512);
896 SSVAL(outbuf,smb_vwv3,dfree);
899 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
901 END_PROFILE(SMBdskattr);
905 /****************************************************************************
907 Can be called from SMBsearch, SMBffirst or SMBfunique.
908 ****************************************************************************/
910 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
920 unsigned int numentries = 0;
921 unsigned int maxentries = 0;
922 BOOL finished = False;
929 BOOL check_descend = False;
930 BOOL expect_close = False;
931 BOOL can_open = True;
932 BOOL bad_path = False;
934 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
936 START_PROFILE(SMBsearch);
938 *mask = *directory = *fname = 0;
940 /* If we were called as SMBffirst then we must expect close. */
941 if(CVAL(inbuf,smb_com) == SMBffirst)
944 outsize = set_message(outbuf,1,3,True);
945 maxentries = SVAL(inbuf,smb_vwv0);
946 dirtype = SVAL(inbuf,smb_vwv1);
947 p = smb_buf(inbuf) + 1;
948 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
949 if (!NT_STATUS_IS_OK(nt_status)) {
950 END_PROFILE(SMBsearch);
951 return ERROR_NT(nt_status);
954 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
957 status_len = SVAL(p, 0);
960 /* dirtype &= ~aDIR; */
962 if (status_len == 0) {
963 SMB_STRUCT_STAT sbuf;
966 pstrcpy(directory,path);
968 unix_convert(directory,conn,0,&bad_path,&sbuf);
971 if (!check_name(directory,conn))
974 p = strrchr_m(dir2,'/');
983 p = strrchr_m(directory,'/');
989 if (strlen(directory) == 0)
990 pstrcpy(directory,".");
991 memset((char *)status,'\0',21);
992 SCVAL(status,0,(dirtype & 0x1F));
997 status_dirtype = CVAL(status,0) & 0x1F;
998 if (status_dirtype != (dirtype & 0x1F))
999 dirtype = status_dirtype;
1001 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1004 string_set(&conn->dirpath,dptr_path(dptr_num));
1005 pstrcpy(mask, dptr_wcard(dptr_num));
1009 p = smb_buf(outbuf) + 3;
1012 if (status_len == 0) {
1013 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1015 if(dptr_num == -2) {
1016 END_PROFILE(SMBsearch);
1017 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1019 END_PROFILE(SMBsearch);
1020 return ERROR_DOS(ERRDOS,ERRnofids);
1022 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1023 END_PROFILE(SMBsearch);
1024 return ERROR_DOS(ERRDOS,ERRnomem);
1027 dirtype = dptr_attr(dptr_num);
1030 DEBUG(4,("dptr_num is %d\n",dptr_num));
1033 if ((dirtype&0x1F) == aVOLID) {
1034 memcpy(p,status,21);
1035 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1036 0,aVOLID,0,!allow_long_path_components);
1037 dptr_fill(p+12,dptr_num);
1038 if (dptr_zero(p+12) && (status_len==0))
1042 p += DIR_STRUCT_SIZE;
1045 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1047 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1048 conn->dirpath,lp_dontdescend(SNUM(conn))));
1049 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1050 check_descend = True;
1052 for (i=numentries;(i<maxentries) && !finished;i++) {
1053 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1055 memcpy(p,status,21);
1056 make_dir_struct(p,mask,fname,size, mode,date,
1057 !allow_long_path_components);
1058 dptr_fill(p+12,dptr_num);
1060 p += DIR_STRUCT_SIZE;
1070 /* If we were called as SMBffirst with smb_search_id == NULL
1071 and no entries were found then return error and close dirptr
1074 if (numentries == 0 || !ok) {
1075 dptr_close(&dptr_num);
1076 } else if(ok && expect_close && status_len == 0) {
1077 /* Close the dptr - we know it's gone */
1078 dptr_close(&dptr_num);
1081 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1082 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1083 dptr_close(&dptr_num);
1086 if ((numentries == 0) && !ms_has_wild(mask)) {
1087 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1090 SSVAL(outbuf,smb_vwv0,numentries);
1091 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1092 SCVAL(smb_buf(outbuf),0,5);
1093 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1095 /* The replies here are never long name. */
1096 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1097 if (!allow_long_path_components) {
1098 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1101 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1102 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1104 outsize += DIR_STRUCT_SIZE*numentries;
1105 smb_setlen(outbuf,outsize - 4);
1107 if ((! *directory) && dptr_path(dptr_num))
1108 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1110 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1111 smb_fn_name(CVAL(inbuf,smb_com)),
1112 mask, directory, dirtype, numentries, maxentries ) );
1114 END_PROFILE(SMBsearch);
1118 /****************************************************************************
1119 Reply to a fclose (stop directory search).
1120 ****************************************************************************/
1122 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1132 START_PROFILE(SMBfclose);
1134 outsize = set_message(outbuf,1,0,True);
1135 p = smb_buf(inbuf) + 1;
1136 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1137 if (!NT_STATUS_IS_OK(err)) {
1138 END_PROFILE(SMBfclose);
1139 return ERROR_NT(err);
1142 status_len = SVAL(p,0);
1145 if (status_len == 0) {
1146 END_PROFILE(SMBfclose);
1147 return ERROR_DOS(ERRSRV,ERRsrverror);
1150 memcpy(status,p,21);
1152 if(dptr_fetch(status+12,&dptr_num)) {
1153 /* Close the dptr - we know it's gone */
1154 dptr_close(&dptr_num);
1157 SSVAL(outbuf,smb_vwv0,0);
1159 DEBUG(3,("search close\n"));
1161 END_PROFILE(SMBfclose);
1165 /****************************************************************************
1167 ****************************************************************************/
1169 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1178 SMB_STRUCT_STAT sbuf;
1179 BOOL bad_path = False;
1181 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1182 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1184 START_PROFILE(SMBopen);
1186 share_mode = SVAL(inbuf,smb_vwv0);
1188 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 END_PROFILE(SMBopen);
1191 return ERROR_NT(status);
1194 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1196 unix_convert(fname,conn,0,&bad_path,&sbuf);
1198 END_PROFILE(SMBopen);
1199 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1202 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1203 (uint32)dos_attr, oplock_request,&rmode,NULL);
1206 END_PROFILE(SMBopen);
1207 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1208 /* We have re-scheduled this call. */
1211 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1214 size = sbuf.st_size;
1215 fmode = dos_mode(conn,fname,&sbuf);
1216 mtime = sbuf.st_mtime;
1219 DEBUG(3,("attempt to open a directory %s\n",fname));
1220 close_file(fsp,False);
1221 END_PROFILE(SMBopen);
1222 return ERROR_DOS(ERRDOS,ERRnoaccess);
1225 outsize = set_message(outbuf,7,0,True);
1226 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1227 SSVAL(outbuf,smb_vwv1,fmode);
1228 if(lp_dos_filetime_resolution(SNUM(conn)) )
1229 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1231 put_dos_date3(outbuf,smb_vwv2,mtime);
1232 SIVAL(outbuf,smb_vwv4,(uint32)size);
1233 SSVAL(outbuf,smb_vwv6,rmode);
1235 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1236 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1238 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1239 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1240 END_PROFILE(SMBopen);
1244 /****************************************************************************
1245 Reply to an open and X.
1246 ****************************************************************************/
1248 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1251 int smb_mode = SVAL(inbuf,smb_vwv3);
1252 int smb_attr = SVAL(inbuf,smb_vwv5);
1253 /* Breakout the oplock request bits so we can set the
1254 reply bits separately. */
1255 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1256 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1257 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1259 int open_flags = SVAL(inbuf,smb_vwv2);
1260 int smb_sattr = SVAL(inbuf,smb_vwv4);
1261 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1263 int smb_ofun = SVAL(inbuf,smb_vwv8);
1265 int fmode=0,mtime=0,rmode=0;
1266 SMB_STRUCT_STAT sbuf;
1268 BOOL bad_path = False;
1271 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1272 ssize_t retval = -1;
1274 START_PROFILE(SMBopenX);
1276 /* If it's an IPC, pass off the pipe handler. */
1278 if (lp_nt_pipe_support()) {
1279 END_PROFILE(SMBopenX);
1280 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1282 END_PROFILE(SMBopenX);
1283 return ERROR_DOS(ERRSRV,ERRaccess);
1287 /* XXXX we need to handle passed times, sattr and flags */
1288 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 END_PROFILE(SMBopenX);
1291 return ERROR_NT(status);
1294 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1296 unix_convert(fname,conn,0,&bad_path,&sbuf);
1298 END_PROFILE(SMBopenX);
1299 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1302 /* Strange open mode mapping. */
1303 if (smb_ofun == 0) {
1304 if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) {
1305 smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
1307 END_PROFILE(SMBopenX);
1308 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1312 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1313 oplock_request, &rmode,&smb_action);
1316 END_PROFILE(SMBopenX);
1317 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1318 /* We have re-scheduled this call. */
1321 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1324 size = sbuf.st_size;
1326 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1327 if the file is truncated or created. */
1328 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1329 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1330 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1331 close_file(fsp,False);
1332 END_PROFILE(SMBntcreateX);
1333 return ERROR_NT(NT_STATUS_DISK_FULL);
1335 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1337 close_file(fsp,False);
1338 END_PROFILE(SMBwrite);
1339 return ERROR_NT(NT_STATUS_DISK_FULL);
1341 size = get_allocation_size(conn,fsp,&sbuf);
1344 fmode = dos_mode(conn,fname,&sbuf);
1345 mtime = sbuf.st_mtime;
1347 close_file(fsp,False);
1348 END_PROFILE(SMBopenX);
1349 return ERROR_DOS(ERRDOS,ERRnoaccess);
1352 /* If the caller set the extended oplock request bit
1353 and we granted one (by whatever means) - set the
1354 correct bit for extended oplock reply.
1357 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1358 smb_action |= EXTENDED_OPLOCK_GRANTED;
1360 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1361 smb_action |= EXTENDED_OPLOCK_GRANTED;
1363 /* If the caller set the core oplock request bit
1364 and we granted one (by whatever means) - set the
1365 correct bit for core oplock reply.
1368 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1369 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1371 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1372 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1374 set_message(outbuf,15,0,True);
1375 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1376 SSVAL(outbuf,smb_vwv3,fmode);
1377 if(lp_dos_filetime_resolution(SNUM(conn)) )
1378 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1380 put_dos_date3(outbuf,smb_vwv4,mtime);
1381 SIVAL(outbuf,smb_vwv6,(uint32)size);
1382 SSVAL(outbuf,smb_vwv8,rmode);
1383 SSVAL(outbuf,smb_vwv11,smb_action);
1385 END_PROFILE(SMBopenX);
1386 return chain_reply(inbuf,outbuf,length,bufsize);
1389 /****************************************************************************
1390 Reply to a SMBulogoffX.
1391 ****************************************************************************/
1393 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1395 uint16 vuid = SVAL(inbuf,smb_uid);
1396 user_struct *vuser = get_valid_user_struct(vuid);
1397 START_PROFILE(SMBulogoffX);
1400 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1402 /* in user level security we are supposed to close any files
1403 open by this user */
1404 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1405 file_close_user(vuid);
1407 invalidate_vuid(vuid);
1409 set_message(outbuf,2,0,True);
1411 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1413 END_PROFILE(SMBulogoffX);
1414 return chain_reply(inbuf,outbuf,length,bufsize);
1417 /****************************************************************************
1418 Reply to a mknew or a create.
1419 ****************************************************************************/
1421 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1428 BOOL bad_path = False;
1430 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1431 SMB_STRUCT_STAT sbuf;
1433 START_PROFILE(SMBcreate);
1435 com = SVAL(inbuf,smb_com);
1437 createmode = SVAL(inbuf,smb_vwv0);
1438 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 END_PROFILE(SMBcreate);
1441 return ERROR_NT(status);
1444 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1446 unix_convert(fname,conn,0,&bad_path,&sbuf);
1448 END_PROFILE(SMBcreate);
1449 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1452 if (createmode & aVOLID)
1453 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1455 if(com == SMBmknew) {
1456 /* We should fail if file exists. */
1457 ofun = FILE_CREATE_IF_NOT_EXIST;
1459 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1460 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1463 /* Open file in dos compatibility share mode. */
1464 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1465 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1468 END_PROFILE(SMBcreate);
1469 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1470 /* We have re-scheduled this call. */
1473 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1476 outsize = set_message(outbuf,1,0,True);
1477 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1479 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1480 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1482 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1483 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1485 DEBUG( 2, ( "new file %s\n", fname ) );
1486 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1488 END_PROFILE(SMBcreate);
1492 /****************************************************************************
1493 Reply to a create temporary file.
1494 ****************************************************************************/
1496 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1501 BOOL bad_path = False;
1503 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1505 SMB_STRUCT_STAT sbuf;
1508 unsigned int namelen;
1510 START_PROFILE(SMBctemp);
1512 createattr = SVAL(inbuf,smb_vwv0);
1513 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 END_PROFILE(SMBctemp);
1516 return ERROR_NT(status);
1519 pstrcat(fname,"/TMXXXXXX");
1521 pstrcat(fname,"TMXXXXXX");
1524 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1526 unix_convert(fname,conn,0,&bad_path,&sbuf);
1528 END_PROFILE(SMBctemp);
1529 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1532 tmpfd = smb_mkstemp(fname);
1534 END_PROFILE(SMBctemp);
1535 return(UNIXERROR(ERRDOS,ERRnoaccess));
1538 SMB_VFS_STAT(conn,fname,&sbuf);
1540 /* Open file in dos compatibility share mode. */
1541 /* We should fail if file does not exist. */
1542 fsp = open_file_shared(conn,fname,&sbuf,
1543 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1544 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1545 (uint32)createattr, oplock_request, NULL, NULL);
1547 /* close fd from smb_mkstemp() */
1551 END_PROFILE(SMBctemp);
1552 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1553 /* We have re-scheduled this call. */
1556 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1559 outsize = set_message(outbuf,1,0,True);
1560 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1562 /* the returned filename is relative to the directory */
1563 s = strrchr_m(fname, '/');
1569 p = smb_buf(outbuf);
1571 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1572 thing in the byte section. JRA */
1573 SSVALS(p, 0, -1); /* what is this? not in spec */
1575 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1577 outsize = set_message_end(outbuf, p);
1579 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1580 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1582 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1583 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1585 DEBUG( 2, ( "created temp file %s\n", fname ) );
1586 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1587 fname, fsp->fd, sbuf.st_mode ) );
1589 END_PROFILE(SMBctemp);
1593 /*******************************************************************
1594 Check if a user is allowed to rename a file.
1595 ********************************************************************/
1597 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1604 if (!CAN_WRITE(conn))
1605 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1607 fmode = dos_mode(conn,fname,pst);
1608 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1609 return NT_STATUS_NO_SUCH_FILE;
1611 if (S_ISDIR(pst->st_mode))
1612 return NT_STATUS_OK;
1614 /* We need a better way to return NT status codes from open... */
1615 set_saved_error_triple(0, 0, NT_STATUS_OK);
1617 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1618 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1622 if (get_saved_error_triple(NULL, NULL, &ret)) {
1623 set_saved_error_triple(0, 0, NT_STATUS_OK);
1626 set_saved_error_triple(0, 0, NT_STATUS_OK);
1627 return NT_STATUS_ACCESS_DENIED;
1629 close_file(fsp,False);
1630 return NT_STATUS_OK;
1633 /*******************************************************************
1634 Check if a user is allowed to delete a file.
1635 ********************************************************************/
1637 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1639 SMB_STRUCT_STAT sbuf;
1645 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1648 if (!CAN_WRITE(conn))
1649 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1651 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1652 if(errno == ENOENT) {
1654 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1656 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1658 return map_nt_error_from_unix(errno);
1661 fmode = dos_mode(conn,fname,&sbuf);
1663 /* Can't delete a directory. */
1665 return NT_STATUS_FILE_IS_A_DIRECTORY;
1667 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1668 return NT_STATUS_OBJECT_NAME_INVALID;
1669 #endif /* JRATEST */
1671 if (!lp_delete_readonly(SNUM(conn))) {
1673 return NT_STATUS_CANNOT_DELETE;
1675 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1676 return NT_STATUS_NO_SUCH_FILE;
1678 if (check_is_at_open) {
1679 if (!can_delete_file_in_directory(conn, fname)) {
1680 return NT_STATUS_ACCESS_DENIED;
1683 /* On open checks the open itself will check the share mode, so
1684 don't do it here as we'll get it wrong. */
1686 /* We need a better way to return NT status codes from open... */
1687 set_saved_error_triple(0, 0, NT_STATUS_OK);
1689 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1690 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1694 if (get_saved_error_triple(NULL, NULL, &ret)) {
1695 set_saved_error_triple(0, 0, NT_STATUS_OK);
1698 set_saved_error_triple(0, 0, NT_STATUS_OK);
1699 return NT_STATUS_ACCESS_DENIED;
1701 close_file(fsp,False);
1703 return NT_STATUS_OK;
1706 /****************************************************************************
1707 The guts of the unlink command, split out so it may be called by the NT SMB
1709 ****************************************************************************/
1711 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1717 NTSTATUS error = NT_STATUS_OK;
1719 BOOL bad_path = False;
1721 SMB_STRUCT_STAT sbuf;
1723 *directory = *mask = 0;
1725 /* We must check for wildcards in the name given
1726 * directly by the client - before any unmangling.
1727 * This prevents an unmangling of a UNIX name containing
1728 * a DOS wildcard like '*' or '?' from unmangling into
1729 * a wildcard delete which was not intended.
1730 * FIX for #226. JRA.
1733 has_wild = ms_has_wild(name);
1735 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1737 p = strrchr_m(name,'/');
1739 pstrcpy(directory,".");
1743 pstrcpy(directory,name);
1748 * We should only check the mangled cache
1749 * here if unix_convert failed. This means
1750 * that the path in 'mask' doesn't exist
1751 * on the file system and so we need to look
1752 * for a possible mangle. This patch from
1753 * Tine Smukavec <valentin.smukavec@hermes.si>.
1756 if (!rc && mangle_is_mangled(mask))
1757 mangle_check_cache( mask, sizeof(pstring)-1 );
1760 pstrcat(directory,"/");
1761 pstrcat(directory,mask);
1762 error = can_delete(conn,directory,dirtype,bad_path,False);
1763 if (!NT_STATUS_IS_OK(error))
1766 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1770 struct smb_Dir *dir_hnd = NULL;
1773 if (check_name(directory,conn))
1774 dir_hnd = OpenDir(conn, directory);
1776 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1777 the pattern matches against the long name, otherwise the short name
1778 We don't implement this yet XXXX
1783 error = NT_STATUS_NO_SUCH_FILE;
1785 if (strequal(mask,"????????.???"))
1788 while ((dname = ReadDirName(dir_hnd, &offset))) {
1791 BOOL sys_direntry = False;
1792 pstrcpy(fname,dname);
1794 if (!is_visible_file(conn, directory, dname, &st, True)) {
1798 /* Quick check for "." and ".." */
1799 if (fname[0] == '.') {
1800 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1801 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1802 sys_direntry = True;
1809 if(!mask_match(fname, mask, conn->case_sensitive))
1813 error = NT_STATUS_OBJECT_NAME_INVALID;
1814 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1819 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1820 error = can_delete(conn,fname,dirtype,bad_path,False);
1821 if (!NT_STATUS_IS_OK(error)) {
1824 if (SMB_VFS_UNLINK(conn,fname) == 0)
1826 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1832 if (count == 0 && NT_STATUS_IS_OK(error)) {
1833 error = map_nt_error_from_unix(errno);
1839 /****************************************************************************
1841 ****************************************************************************/
1843 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1850 START_PROFILE(SMBunlink);
1852 dirtype = SVAL(inbuf,smb_vwv0);
1854 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 END_PROFILE(SMBunlink);
1857 return ERROR_NT(status);
1860 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1862 DEBUG(3,("reply_unlink : %s\n",name));
1864 status = unlink_internals(conn, dirtype, name);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1867 /* We have re-scheduled this call. */
1870 return ERROR_NT(status);
1874 * Win2k needs a changenotify request response before it will
1875 * update after a rename..
1877 process_pending_change_notify_queue((time_t)0);
1879 outsize = set_message(outbuf,0,0,True);
1881 END_PROFILE(SMBunlink);
1885 /****************************************************************************
1887 ****************************************************************************/
1889 static void fail_readraw(void)
1892 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1894 exit_server(errstr);
1897 #if defined(WITH_SENDFILE)
1898 /****************************************************************************
1899 Fake (read/write) sendfile. Returns -1 on read or write fail.
1900 ****************************************************************************/
1902 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1906 /* Paranioa check... */
1907 if (nread > bufsize) {
1912 ret = read_file(fsp,buf,startpos,nread);
1918 /* If we had a short read, fill with zeros. */
1920 memset(buf, '\0', nread - ret);
1923 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1927 return (ssize_t)nread;
1931 /****************************************************************************
1932 Use sendfile in readbraw.
1933 ****************************************************************************/
1935 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1936 ssize_t mincount, char *outbuf, int out_buffsize)
1940 #if defined(WITH_SENDFILE)
1942 * We can only use sendfile on a non-chained packet
1943 * but we can use on a non-oplocked file. tridge proved this
1944 * on a train in Germany :-). JRA.
1945 * reply_readbraw has already checked the length.
1948 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1951 _smb_setlen(outbuf,nread);
1952 header.data = outbuf;
1956 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1957 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1958 if (errno == ENOSYS) {
1959 goto normal_readbraw;
1963 * Special hack for broken Linux with no working sendfile. If we
1964 * return EINTR we sent the header but not the rest of the data.
1965 * Fake this up by doing read/write calls.
1967 if (errno == EINTR) {
1968 /* Ensure we don't do this again. */
1969 set_use_sendfile(SNUM(conn), False);
1970 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1972 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1973 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1974 fsp->fsp_name, strerror(errno) ));
1975 exit_server("send_file_readbraw fake_sendfile failed");
1980 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1981 fsp->fsp_name, strerror(errno) ));
1982 exit_server("send_file_readbraw sendfile failed");
1992 ret = read_file(fsp,outbuf+4,startpos,nread);
1993 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2002 _smb_setlen(outbuf,ret);
2003 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2007 /****************************************************************************
2008 Reply to a readbraw (core+ protocol).
2009 ****************************************************************************/
2011 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2013 extern struct current_user current_user;
2014 ssize_t maxcount,mincount;
2017 char *header = outbuf;
2019 START_PROFILE(SMBreadbraw);
2021 if (srv_is_signing_active()) {
2022 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2026 * Special check if an oplock break has been issued
2027 * and the readraw request croses on the wire, we must
2028 * return a zero length response here.
2031 if(global_oplock_break) {
2032 _smb_setlen(header,0);
2033 if (write_data(smbd_server_fd(),header,4) != 4)
2035 DEBUG(5,("readbraw - oplock break finished\n"));
2036 END_PROFILE(SMBreadbraw);
2040 fsp = file_fsp(inbuf,smb_vwv0);
2042 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2044 * fsp could be NULL here so use the value from the packet. JRA.
2046 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2047 _smb_setlen(header,0);
2048 if (write_data(smbd_server_fd(),header,4) != 4)
2050 END_PROFILE(SMBreadbraw);
2054 CHECK_FSP(fsp,conn);
2056 flush_write_cache(fsp, READRAW_FLUSH);
2058 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2059 if(CVAL(inbuf,smb_wct) == 10) {
2061 * This is a large offset (64 bit) read.
2063 #ifdef LARGE_SMB_OFF_T
2065 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2067 #else /* !LARGE_SMB_OFF_T */
2070 * Ensure we haven't been sent a >32 bit offset.
2073 if(IVAL(inbuf,smb_vwv8) != 0) {
2074 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2075 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2076 _smb_setlen(header,0);
2077 if (write_data(smbd_server_fd(),header,4) != 4)
2079 END_PROFILE(SMBreadbraw);
2083 #endif /* LARGE_SMB_OFF_T */
2086 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2087 _smb_setlen(header,0);
2088 if (write_data(smbd_server_fd(),header,4) != 4)
2090 END_PROFILE(SMBreadbraw);
2094 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2095 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2097 /* ensure we don't overrun the packet size */
2098 maxcount = MIN(65535,maxcount);
2100 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2101 SMB_OFF_T size = fsp->size;
2102 SMB_OFF_T sizeneeded = startpos + maxcount;
2104 if (size < sizeneeded) {
2106 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
2108 if (!fsp->can_write)
2112 if (startpos >= size)
2115 nread = MIN(maxcount,(size - startpos));
2118 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2119 if (nread < mincount)
2123 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2124 (int)maxcount, (int)mincount, (int)nread ) );
2126 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2128 DEBUG(5,("readbraw finished\n"));
2129 END_PROFILE(SMBreadbraw);
2133 /****************************************************************************
2134 Reply to a lockread (core+ protocol).
2135 ****************************************************************************/
2137 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2145 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2146 BOOL my_lock_ctx = False;
2147 START_PROFILE(SMBlockread);
2149 CHECK_FSP(fsp,conn);
2152 release_level_2_oplocks_on_change(fsp);
2154 numtoread = SVAL(inbuf,smb_vwv1);
2155 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2157 outsize = set_message(outbuf,5,3,True);
2158 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2159 data = smb_buf(outbuf) + 3;
2162 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2163 * protocol request that predates the read/write lock concept.
2164 * Thus instead of asking for a read lock here we need to ask
2165 * for a write lock. JRA.
2166 * Note that the requested lock size is unaffected by max_recv.
2169 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2170 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2172 if (NT_STATUS_V(status)) {
2175 * We used to make lockread a blocking lock. It turns out
2176 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2180 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2182 * A blocking lock was requested. Package up
2183 * this smb into a queued request and push it
2184 * onto the blocking lock queue.
2186 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2187 (SMB_BIG_UINT)numtoread)) {
2188 END_PROFILE(SMBlockread);
2193 END_PROFILE(SMBlockread);
2194 return ERROR_NT(status);
2198 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2201 if (numtoread > max_recv) {
2202 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2203 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2204 (unsigned int)numtoread, (unsigned int)max_recv ));
2205 numtoread = MIN(numtoread,max_recv);
2207 nread = read_file(fsp,data,startpos,numtoread);
2210 END_PROFILE(SMBlockread);
2211 return(UNIXERROR(ERRDOS,ERRnoaccess));
2215 SSVAL(outbuf,smb_vwv0,nread);
2216 SSVAL(outbuf,smb_vwv5,nread+3);
2217 SSVAL(smb_buf(outbuf),1,nread);
2219 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2220 fsp->fnum, (int)numtoread, (int)nread));
2222 END_PROFILE(SMBlockread);
2226 /****************************************************************************
2228 ****************************************************************************/
2230 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2237 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2238 START_PROFILE(SMBread);
2240 CHECK_FSP(fsp,conn);
2243 numtoread = SVAL(inbuf,smb_vwv1);
2244 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2246 outsize = set_message(outbuf,5,3,True);
2247 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2249 * The requested read size cannot be greater than max_recv. JRA.
2251 if (numtoread > max_recv) {
2252 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2253 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2254 (unsigned int)numtoread, (unsigned int)max_recv ));
2255 numtoread = MIN(numtoread,max_recv);
2258 data = smb_buf(outbuf) + 3;
2260 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2261 END_PROFILE(SMBread);
2262 return ERROR_DOS(ERRDOS,ERRlock);
2266 nread = read_file(fsp,data,startpos,numtoread);
2269 END_PROFILE(SMBread);
2270 return(UNIXERROR(ERRDOS,ERRnoaccess));
2274 SSVAL(outbuf,smb_vwv0,nread);
2275 SSVAL(outbuf,smb_vwv5,nread+3);
2276 SCVAL(smb_buf(outbuf),0,1);
2277 SSVAL(smb_buf(outbuf),1,nread);
2279 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2280 fsp->fnum, (int)numtoread, (int)nread ) );
2282 END_PROFILE(SMBread);
2286 /****************************************************************************
2287 Reply to a read and X - possibly using sendfile.
2288 ****************************************************************************/
2290 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2291 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2295 char *data = smb_buf(outbuf);
2297 #if defined(WITH_SENDFILE)
2299 * We can only use sendfile on a non-chained packet
2300 * but we can use on a non-oplocked file. tridge proved this
2301 * on a train in Germany :-). JRA.
2304 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2305 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2306 SMB_STRUCT_STAT sbuf;
2309 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2310 return(UNIXERROR(ERRDOS,ERRnoaccess));
2312 if (startpos > sbuf.st_size)
2315 if (smb_maxcnt > (sbuf.st_size - startpos))
2316 smb_maxcnt = (sbuf.st_size - startpos);
2318 if (smb_maxcnt == 0)
2322 * Set up the packet header before send. We
2323 * assume here the sendfile will work (get the
2324 * correct amount of data).
2327 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2328 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2329 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2330 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2331 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2332 SCVAL(outbuf,smb_vwv0,0xFF);
2333 set_message(outbuf,12,smb_maxcnt,False);
2334 header.data = outbuf;
2335 header.length = data - outbuf;
2338 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2339 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2340 if (errno == ENOSYS) {
2345 * Special hack for broken Linux with no working sendfile. If we
2346 * return EINTR we sent the header but not the rest of the data.
2347 * Fake this up by doing read/write calls.
2350 if (errno == EINTR) {
2351 /* Ensure we don't do this again. */
2352 set_use_sendfile(SNUM(conn), False);
2353 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2355 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2356 len_outbuf - (data-outbuf))) == -1) {
2357 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2358 fsp->fsp_name, strerror(errno) ));
2359 exit_server("send_file_readX: fake_sendfile failed");
2361 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2362 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2363 /* Returning -1 here means successful sendfile. */
2367 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2368 fsp->fsp_name, strerror(errno) ));
2369 exit_server("send_file_readX sendfile failed");
2372 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2373 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2374 /* Returning -1 here means successful sendfile. */
2382 nread = read_file(fsp,data,startpos,smb_maxcnt);
2385 END_PROFILE(SMBreadX);
2386 return(UNIXERROR(ERRDOS,ERRnoaccess));
2389 outsize = set_message(outbuf,12,nread,False);
2390 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2391 SSVAL(outbuf,smb_vwv5,nread);
2392 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2393 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2394 SSVAL(smb_buf(outbuf),-2,nread);
2396 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2397 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2399 /* Returning the number of bytes we want to send back - including header. */
2403 /****************************************************************************
2404 Reply to a read and X.
2405 ****************************************************************************/
2407 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2409 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2410 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2412 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2414 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2417 START_PROFILE(SMBreadX);
2419 /* If it's an IPC, pass off the pipe handler. */
2421 END_PROFILE(SMBreadX);
2422 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2425 CHECK_FSP(fsp,conn);
2428 set_message(outbuf,12,0,True);
2430 if (global_client_caps & CAP_LARGE_READX) {
2431 if (SVAL(inbuf,smb_vwv7) == 1) {
2432 smb_maxcnt |= (1<<16);
2434 if (smb_maxcnt > BUFFER_SIZE) {
2435 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2436 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2437 END_PROFILE(SMBreadX);
2438 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2442 if(CVAL(inbuf,smb_wct) == 12) {
2443 #ifdef LARGE_SMB_OFF_T
2445 * This is a large offset (64 bit) read.
2447 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2449 #else /* !LARGE_SMB_OFF_T */
2452 * Ensure we haven't been sent a >32 bit offset.
2455 if(IVAL(inbuf,smb_vwv10) != 0) {
2456 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2457 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2458 END_PROFILE(SMBreadX);
2459 return ERROR_DOS(ERRDOS,ERRbadaccess);
2462 #endif /* LARGE_SMB_OFF_T */
2466 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2467 END_PROFILE(SMBreadX);
2468 return ERROR_DOS(ERRDOS,ERRlock);
2471 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2473 nread = chain_reply(inbuf,outbuf,length,bufsize);
2475 END_PROFILE(SMBreadX);
2479 /****************************************************************************
2480 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2481 ****************************************************************************/
2483 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2486 ssize_t total_written=0;
2487 size_t numtowrite=0;
2492 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2494 START_PROFILE(SMBwritebraw);
2496 if (srv_is_signing_active()) {
2497 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2500 CHECK_FSP(fsp,conn);
2503 tcount = IVAL(inbuf,smb_vwv1);
2504 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2505 write_through = BITSETW(inbuf+smb_vwv7,0);
2507 /* We have to deal with slightly different formats depending
2508 on whether we are using the core+ or lanman1.0 protocol */
2510 if(Protocol <= PROTOCOL_COREPLUS) {
2511 numtowrite = SVAL(smb_buf(inbuf),-2);
2512 data = smb_buf(inbuf);
2514 numtowrite = SVAL(inbuf,smb_vwv10);
2515 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2518 /* force the error type */
2519 SCVAL(inbuf,smb_com,SMBwritec);
2520 SCVAL(outbuf,smb_com,SMBwritec);
2522 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2523 END_PROFILE(SMBwritebraw);
2524 return(ERROR_DOS(ERRDOS,ERRlock));
2528 nwritten = write_file(fsp,data,startpos,numtowrite);
2530 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2531 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2533 if (nwritten < (ssize_t)numtowrite) {
2534 END_PROFILE(SMBwritebraw);
2535 return(UNIXERROR(ERRHRD,ERRdiskfull));
2538 total_written = nwritten;
2540 /* Return a message to the redirector to tell it to send more bytes */
2541 SCVAL(outbuf,smb_com,SMBwritebraw);
2542 SSVALS(outbuf,smb_vwv0,-1);
2543 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2544 if (!send_smb(smbd_server_fd(),outbuf))
2545 exit_server("reply_writebraw: send_smb failed.");
2547 /* Now read the raw data into the buffer and write it */
2548 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2549 exit_server("secondary writebraw failed");
2552 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2553 numtowrite = smb_len(inbuf);
2555 /* Set up outbuf to return the correct return */
2556 outsize = set_message(outbuf,1,0,True);
2557 SCVAL(outbuf,smb_com,SMBwritec);
2558 SSVAL(outbuf,smb_vwv0,total_written);
2560 if (numtowrite != 0) {
2562 if (numtowrite > BUFFER_SIZE) {
2563 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2564 (unsigned int)numtowrite ));
2565 exit_server("secondary writebraw failed");
2568 if (tcount > nwritten+numtowrite) {
2569 DEBUG(3,("Client overestimated the write %d %d %d\n",
2570 (int)tcount,(int)nwritten,(int)numtowrite));
2573 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2574 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2576 exit_server("secondary writebraw failed");
2579 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2581 if (nwritten < (ssize_t)numtowrite) {
2582 SCVAL(outbuf,smb_rcls,ERRHRD);
2583 SSVAL(outbuf,smb_err,ERRdiskfull);
2587 total_written += nwritten;
2590 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2591 sync_file(conn,fsp);
2593 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2594 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2596 /* we won't return a status if write through is not selected - this follows what WfWg does */
2597 END_PROFILE(SMBwritebraw);
2598 if (!write_through && total_written==tcount) {
2600 #if RABBIT_PELLET_FIX
2602 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2603 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2605 if (!send_keepalive(smbd_server_fd()))
2606 exit_server("reply_writebraw: send of keepalive failed");
2614 /****************************************************************************
2615 Reply to a writeunlock (core+).
2616 ****************************************************************************/
2618 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2619 int size, int dum_buffsize)
2621 ssize_t nwritten = -1;
2625 NTSTATUS status = NT_STATUS_OK;
2626 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2628 START_PROFILE(SMBwriteunlock);
2630 CHECK_FSP(fsp,conn);
2633 numtowrite = SVAL(inbuf,smb_vwv1);
2634 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2635 data = smb_buf(inbuf) + 3;
2637 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2638 END_PROFILE(SMBwriteunlock);
2639 return ERROR_DOS(ERRDOS,ERRlock);
2642 /* The special X/Open SMB protocol handling of
2643 zero length writes is *NOT* done for
2648 nwritten = write_file(fsp,data,startpos,numtowrite);
2650 if (lp_syncalways(SNUM(conn)))
2651 sync_file(conn,fsp);
2653 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2654 END_PROFILE(SMBwriteunlock);
2655 return(UNIXERROR(ERRHRD,ERRdiskfull));
2659 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2660 (SMB_BIG_UINT)startpos);
2661 if (NT_STATUS_V(status)) {
2662 END_PROFILE(SMBwriteunlock);
2663 return ERROR_NT(status);
2667 outsize = set_message(outbuf,1,0,True);
2669 SSVAL(outbuf,smb_vwv0,nwritten);
2671 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2672 fsp->fnum, (int)numtowrite, (int)nwritten));
2674 END_PROFILE(SMBwriteunlock);
2678 /****************************************************************************
2680 ****************************************************************************/
2682 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2685 ssize_t nwritten = -1;
2688 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2690 START_PROFILE(SMBwrite);
2692 /* If it's an IPC, pass off the pipe handler. */
2694 END_PROFILE(SMBwrite);
2695 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2698 CHECK_FSP(fsp,conn);
2701 numtowrite = SVAL(inbuf,smb_vwv1);
2702 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2703 data = smb_buf(inbuf) + 3;
2705 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2706 END_PROFILE(SMBwrite);
2707 return ERROR_DOS(ERRDOS,ERRlock);
2711 * X/Open SMB protocol says that if smb_vwv1 is
2712 * zero then the file size should be extended or
2713 * truncated to the size given in smb_vwv[2-3].
2716 if(numtowrite == 0) {
2718 * This is actually an allocate call, and set EOF. JRA.
2720 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2722 END_PROFILE(SMBwrite);
2723 return ERROR_NT(NT_STATUS_DISK_FULL);
2725 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2727 END_PROFILE(SMBwrite);
2728 return ERROR_NT(NT_STATUS_DISK_FULL);
2731 nwritten = write_file(fsp,data,startpos,numtowrite);
2733 if (lp_syncalways(SNUM(conn)))
2734 sync_file(conn,fsp);
2736 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2737 END_PROFILE(SMBwrite);
2738 return(UNIXERROR(ERRHRD,ERRdiskfull));
2741 outsize = set_message(outbuf,1,0,True);
2743 SSVAL(outbuf,smb_vwv0,nwritten);
2745 if (nwritten < (ssize_t)numtowrite) {
2746 SCVAL(outbuf,smb_rcls,ERRHRD);
2747 SSVAL(outbuf,smb_err,ERRdiskfull);
2750 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2752 END_PROFILE(SMBwrite);
2756 /****************************************************************************
2757 Reply to a write and X.
2758 ****************************************************************************/
2760 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2762 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2763 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2764 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2765 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2766 ssize_t nwritten = -1;
2767 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2768 unsigned int smblen = smb_len(inbuf);
2770 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2771 START_PROFILE(SMBwriteX);
2773 /* If it's an IPC, pass off the pipe handler. */
2775 END_PROFILE(SMBwriteX);
2776 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2779 CHECK_FSP(fsp,conn);
2782 /* Deal with possible LARGE_WRITEX */
2784 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2786 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2787 END_PROFILE(SMBwriteX);
2788 return ERROR_DOS(ERRDOS,ERRbadmem);
2791 data = smb_base(inbuf) + smb_doff;
2793 if(CVAL(inbuf,smb_wct) == 14) {
2794 #ifdef LARGE_SMB_OFF_T
2796 * This is a large offset (64 bit) write.
2798 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2800 #else /* !LARGE_SMB_OFF_T */
2803 * Ensure we haven't been sent a >32 bit offset.
2806 if(IVAL(inbuf,smb_vwv12) != 0) {
2807 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2808 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2809 END_PROFILE(SMBwriteX);
2810 return ERROR_DOS(ERRDOS,ERRbadaccess);
2813 #endif /* LARGE_SMB_OFF_T */
2816 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2817 END_PROFILE(SMBwriteX);
2818 return ERROR_DOS(ERRDOS,ERRlock);
2821 /* X/Open SMB protocol says that, unlike SMBwrite
2822 if the length is zero then NO truncation is
2823 done, just a write of zero. To truncate a file,
2829 nwritten = write_file(fsp,data,startpos,numtowrite);
2831 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2832 END_PROFILE(SMBwriteX);
2833 return(UNIXERROR(ERRHRD,ERRdiskfull));
2836 set_message(outbuf,6,0,True);
2838 SSVAL(outbuf,smb_vwv2,nwritten);
2840 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2842 if (nwritten < (ssize_t)numtowrite) {
2843 SCVAL(outbuf,smb_rcls,ERRHRD);
2844 SSVAL(outbuf,smb_err,ERRdiskfull);
2847 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2848 fsp->fnum, (int)numtowrite, (int)nwritten));
2850 if (lp_syncalways(SNUM(conn)) || write_through)
2851 sync_file(conn,fsp);
2853 END_PROFILE(SMBwriteX);
2854 return chain_reply(inbuf,outbuf,length,bufsize);
2857 /****************************************************************************
2859 ****************************************************************************/
2861 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2867 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2868 START_PROFILE(SMBlseek);
2870 CHECK_FSP(fsp,conn);
2872 flush_write_cache(fsp, SEEK_FLUSH);
2874 mode = SVAL(inbuf,smb_vwv1) & 3;
2875 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2876 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2885 res = fsp->pos + startpos;
2896 if (umode == SEEK_END) {
2897 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2898 if(errno == EINVAL) {
2899 SMB_OFF_T current_pos = startpos;
2900 SMB_STRUCT_STAT sbuf;
2902 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2903 END_PROFILE(SMBlseek);
2904 return(UNIXERROR(ERRDOS,ERRnoaccess));
2907 current_pos += sbuf.st_size;
2909 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2914 END_PROFILE(SMBlseek);
2915 return(UNIXERROR(ERRDOS,ERRnoaccess));
2921 outsize = set_message(outbuf,2,0,True);
2922 SIVAL(outbuf,smb_vwv0,res);
2924 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2925 fsp->fnum, (double)startpos, (double)res, mode));
2927 END_PROFILE(SMBlseek);
2931 /****************************************************************************
2933 ****************************************************************************/
2935 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2937 int outsize = set_message(outbuf,0,0,True);
2938 uint16 fnum = SVAL(inbuf,smb_vwv0);
2939 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2940 START_PROFILE(SMBflush);
2943 CHECK_FSP(fsp,conn);
2946 file_sync_all(conn);
2948 sync_file(conn,fsp);
2951 DEBUG(3,("flush\n"));
2952 END_PROFILE(SMBflush);
2956 /****************************************************************************
2958 ****************************************************************************/
2960 int reply_exit(connection_struct *conn,
2961 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2964 START_PROFILE(SMBexit);
2966 file_close_pid(SVAL(inbuf,smb_pid));
2968 outsize = set_message(outbuf,0,0,True);
2970 DEBUG(3,("exit\n"));
2972 END_PROFILE(SMBexit);
2976 /****************************************************************************
2977 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2978 ****************************************************************************/
2980 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2983 extern struct current_user current_user;
2986 int32 eclass = 0, err = 0;
2987 files_struct *fsp = NULL;
2988 START_PROFILE(SMBclose);
2990 outsize = set_message(outbuf,0,0,True);
2992 /* If it's an IPC, pass off to the pipe handler. */
2994 END_PROFILE(SMBclose);
2995 return reply_pipe_close(conn, inbuf,outbuf);
2998 fsp = file_fsp(inbuf,smb_vwv0);
3001 * We can only use CHECK_FSP if we know it's not a directory.
3004 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3005 END_PROFILE(SMBclose);
3006 return ERROR_DOS(ERRDOS,ERRbadfid);
3009 if(fsp->is_directory) {
3011 * Special case - close NT SMB directory handle.
3013 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3014 close_file(fsp,True);
3017 * Close ordinary file.
3022 /* Save the name for time set in close. */
3023 pstrcpy( file_name, fsp->fsp_name);
3025 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3027 conn->num_files_open));
3030 * Take care of any time sent in the close.
3033 mtime = make_unix_date3(inbuf+smb_vwv1);
3034 fsp_set_pending_modtime(fsp, mtime);
3037 * close_file() returns the unix errno if an error
3038 * was detected on close - normally this is due to
3039 * a disk full error. If not then it was probably an I/O error.
3042 if((close_err = close_file(fsp,True)) != 0) {
3044 END_PROFILE(SMBclose);
3045 return (UNIXERROR(ERRHRD,ERRgeneral));
3049 /* We have a cached error */
3051 END_PROFILE(SMBclose);
3052 return ERROR_DOS(eclass,err);
3055 END_PROFILE(SMBclose);
3059 /****************************************************************************
3060 Reply to a writeclose (Core+ protocol).
3061 ****************************************************************************/
3063 int reply_writeclose(connection_struct *conn,
3064 char *inbuf,char *outbuf, int size, int dum_buffsize)
3067 ssize_t nwritten = -1;
3073 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3074 START_PROFILE(SMBwriteclose);
3076 CHECK_FSP(fsp,conn);
3079 numtowrite = SVAL(inbuf,smb_vwv1);
3080 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3081 mtime = make_unix_date3(inbuf+smb_vwv4);
3082 data = smb_buf(inbuf) + 1;
3084 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3085 END_PROFILE(SMBwriteclose);
3086 return ERROR_DOS(ERRDOS,ERRlock);
3089 nwritten = write_file(fsp,data,startpos,numtowrite);
3091 set_filetime(conn, fsp->fsp_name,mtime);
3094 * More insanity. W2K only closes the file if writelen > 0.
3099 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3101 close_err = close_file(fsp,True);
3104 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3105 fsp->fnum, (int)numtowrite, (int)nwritten,
3106 conn->num_files_open));
3108 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3109 END_PROFILE(SMBwriteclose);
3110 return(UNIXERROR(ERRHRD,ERRdiskfull));
3113 if(close_err != 0) {
3115 END_PROFILE(SMBwriteclose);
3116 return(UNIXERROR(ERRHRD,ERRgeneral));
3119 outsize = set_message(outbuf,1,0,True);
3121 SSVAL(outbuf,smb_vwv0,nwritten);
3122 END_PROFILE(SMBwriteclose);
3126 /****************************************************************************
3128 ****************************************************************************/
3130 int reply_lock(connection_struct *conn,
3131 char *inbuf,char *outbuf, int length, int dum_buffsize)
3133 int outsize = set_message(outbuf,0,0,True);
3134 SMB_BIG_UINT count,offset;
3136 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3137 BOOL my_lock_ctx = False;
3139 START_PROFILE(SMBlock);
3141 CHECK_FSP(fsp,conn);
3143 release_level_2_oplocks_on_change(fsp);
3145 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3146 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3148 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3149 fsp->fd, fsp->fnum, (double)offset, (double)count));
3151 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3152 if (NT_STATUS_V(status)) {
3154 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3155 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3157 * A blocking lock was requested. Package up
3158 * this smb into a queued request and push it
3159 * onto the blocking lock queue.
3161 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3162 END_PROFILE(SMBlock);
3167 END_PROFILE(SMBlock);
3168 return ERROR_NT(status);
3171 END_PROFILE(SMBlock);
3175 /****************************************************************************
3177 ****************************************************************************/
3179 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3182 int outsize = set_message(outbuf,0,0,True);
3183 SMB_BIG_UINT count,offset;
3185 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3186 START_PROFILE(SMBunlock);
3188 CHECK_FSP(fsp,conn);
3190 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3191 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3193 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3194 if (NT_STATUS_V(status)) {
3195 END_PROFILE(SMBunlock);
3196 return ERROR_NT(status);
3199 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3200 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3202 END_PROFILE(SMBunlock);
3206 /****************************************************************************
3208 ****************************************************************************/
3210 int reply_tdis(connection_struct *conn,
3211 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3213 int outsize = set_message(outbuf,0,0,True);
3215 START_PROFILE(SMBtdis);
3217 vuid = SVAL(inbuf,smb_uid);
3220 DEBUG(4,("Invalid connection in tdis\n"));
3221 END_PROFILE(SMBtdis);
3222 return ERROR_DOS(ERRSRV,ERRinvnid);
3227 close_cnum(conn,vuid);
3229 END_PROFILE(SMBtdis);
3233 /****************************************************************************
3235 ****************************************************************************/
3237 int reply_echo(connection_struct *conn,
3238 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3240 int smb_reverb = SVAL(inbuf,smb_vwv0);
3242 unsigned int data_len = smb_buflen(inbuf);
3243 int outsize = set_message(outbuf,1,data_len,True);
3244 START_PROFILE(SMBecho);
3246 if (data_len > BUFFER_SIZE) {
3247 DEBUG(0,("reply_echo: data_len too large.\n"));
3248 END_PROFILE(SMBecho);
3252 /* copy any incoming data back out */
3254 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3256 if (smb_reverb > 100) {
3257 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3261 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3262 SSVAL(outbuf,smb_vwv0,seq_num);
3264 smb_setlen(outbuf,outsize - 4);
3266 if (!send_smb(smbd_server_fd(),outbuf))
3267 exit_server("reply_echo: send_smb failed.");
3270 DEBUG(3,("echo %d times\n", smb_reverb));
3274 END_PROFILE(SMBecho);
3278 /****************************************************************************
3279 Reply to a printopen.
3280 ****************************************************************************/
3282 int reply_printopen(connection_struct *conn,
3283 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3287 START_PROFILE(SMBsplopen);
3289 if (!CAN_PRINT(conn)) {
3290 END_PROFILE(SMBsplopen);
3291 return ERROR_DOS(ERRDOS,ERRnoaccess);
3294 /* Open for exclusive use, write only. */
3295 fsp = print_fsp_open(conn, NULL);
3298 END_PROFILE(SMBsplopen);
3299 return(UNIXERROR(ERRDOS,ERRnoaccess));
3302 outsize = set_message(outbuf,1,0,True);
3303 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3305 DEBUG(3,("openprint fd=%d fnum=%d\n",
3306 fsp->fd, fsp->fnum));
3308 END_PROFILE(SMBsplopen);
3312 /****************************************************************************
3313 Reply to a printclose.
3314 ****************************************************************************/
3316 int reply_printclose(connection_struct *conn,
3317 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3319 int outsize = set_message(outbuf,0,0,True);
3320 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3322 START_PROFILE(SMBsplclose);
3324 CHECK_FSP(fsp,conn);
3326 if (!CAN_PRINT(conn)) {
3327 END_PROFILE(SMBsplclose);
3328 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3331 DEBUG(3,("printclose fd=%d fnum=%d\n",
3332 fsp->fd,fsp->fnum));
3334 close_err = close_file(fsp,True);
3336 if(close_err != 0) {
3338 END_PROFILE(SMBsplclose);
3339 return(UNIXERROR(ERRHRD,ERRgeneral));
3342 END_PROFILE(SMBsplclose);
3346 /****************************************************************************
3347 Reply to a printqueue.
3348 ****************************************************************************/
3350 int reply_printqueue(connection_struct *conn,
3351 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3353 int outsize = set_message(outbuf,2,3,True);
3354 int max_count = SVAL(inbuf,smb_vwv0);
3355 int start_index = SVAL(inbuf,smb_vwv1);
3356 START_PROFILE(SMBsplretq);
3358 /* we used to allow the client to get the cnum wrong, but that
3359 is really quite gross and only worked when there was only
3360 one printer - I think we should now only accept it if they
3361 get it right (tridge) */
3362 if (!CAN_PRINT(conn)) {
3363 END_PROFILE(SMBsplretq);
3364 return ERROR_DOS(ERRDOS,ERRnoaccess);
3367 SSVAL(outbuf,smb_vwv0,0);
3368 SSVAL(outbuf,smb_vwv1,0);
3369 SCVAL(smb_buf(outbuf),0,1);
3370 SSVAL(smb_buf(outbuf),1,0);
3372 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3373 start_index, max_count));
3376 print_queue_struct *queue = NULL;
3377 print_status_struct status;
3378 char *p = smb_buf(outbuf) + 3;
3379 int count = print_queue_status(SNUM(conn), &queue, &status);
3380 int num_to_get = ABS(max_count);
3381 int first = (max_count>0?start_index:start_index+max_count+1);
3387 num_to_get = MIN(num_to_get,count-first);
3390 for (i=first;i<first+num_to_get;i++) {
3391 put_dos_date2(p,0,queue[i].time);
3392 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3393 SSVAL(p,5, queue[i].job);
3394 SIVAL(p,7,queue[i].size);
3396 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3401 outsize = set_message(outbuf,2,28*count+3,False);
3402 SSVAL(outbuf,smb_vwv0,count);
3403 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3404 SCVAL(smb_buf(outbuf),0,1);
3405 SSVAL(smb_buf(outbuf),1,28*count);
3410 DEBUG(3,("%d entries returned in queue\n",count));
3413 END_PROFILE(SMBsplretq);
3417 /****************************************************************************
3418 Reply to a printwrite.
3419 ****************************************************************************/
3421 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3424 int outsize = set_message(outbuf,0,0,True);
3426 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3428 START_PROFILE(SMBsplwr);
3430 if (!CAN_PRINT(conn)) {
3431 END_PROFILE(SMBsplwr);
3432 return ERROR_DOS(ERRDOS,ERRnoaccess);
3435 CHECK_FSP(fsp,conn);
3438 numtowrite = SVAL(smb_buf(inbuf),1);
3439 data = smb_buf(inbuf) + 3;
3441 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3442 END_PROFILE(SMBsplwr);
3443 return(UNIXERROR(ERRHRD,ERRdiskfull));
3446 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3448 END_PROFILE(SMBsplwr);
3452 /****************************************************************************
3453 The guts of the mkdir command, split out so it may be called by the NT SMB
3455 ****************************************************************************/
3457 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3461 if(!CAN_WRITE(conn)) {
3462 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3464 return map_nt_error_from_unix(errno);
3468 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3471 if (!check_name(directory, conn)) {
3472 if(errno == ENOENT) {
3474 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3476 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3479 return map_nt_error_from_unix(errno);
3482 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3484 if(errno == ENOENT) {
3485 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3487 return map_nt_error_from_unix(errno);
3490 return NT_STATUS_OK;
3493 /****************************************************************************
3495 ****************************************************************************/
3497 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3502 BOOL bad_path = False;
3503 SMB_STRUCT_STAT sbuf;
3505 START_PROFILE(SMBmkdir);
3507 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3508 if (!NT_STATUS_IS_OK(status)) {
3509 END_PROFILE(SMBmkdir);
3510 return ERROR_NT(status);
3513 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3515 unix_convert(directory,conn,0,&bad_path,&sbuf);
3517 if( strchr_m(directory, ':')) {
3518 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3519 END_PROFILE(SMBmkdir);
3520 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3523 status = mkdir_internal(conn, directory,bad_path);
3524 if (!NT_STATUS_IS_OK(status)) {
3525 END_PROFILE(SMBmkdir);
3526 return ERROR_NT(status);
3529 if (lp_inherit_owner(SNUM(conn))) {
3530 /* Ensure we're checking for a symlink here.... */
3531 /* We don't want to get caught by a symlink racer. */
3533 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3534 END_PROFILE(SMBmkdir);
3535 return(UNIXERROR(ERRDOS,ERRnoaccess));
3538 if(!S_ISDIR(sbuf.st_mode)) {
3539 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3540 END_PROFILE(SMBmkdir);
3541 return(UNIXERROR(ERRDOS,ERRnoaccess));
3544 change_owner_to_parent(conn, NULL, directory, &sbuf);
3547 outsize = set_message(outbuf,0,0,True);
3549 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3551 END_PROFILE(SMBmkdir);
3555 /****************************************************************************
3556 Static function used by reply_rmdir to delete an entire directory
3557 tree recursively. Return False on ok, True on fail.
3558 ****************************************************************************/
3560 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3562 const char *dname = NULL;
3565 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3570 while((dname = ReadDirName(dir_hnd, &offset))) {
3574 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3577 if (!is_visible_file(conn, directory, dname, &st, False))
3580 /* Construct the full name. */
3581 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3587 pstrcpy(fullname, directory);
3588 pstrcat(fullname, "/");
3589 pstrcat(fullname, dname);
3591 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3596 if(st.st_mode & S_IFDIR) {
3597 if(recursive_rmdir(conn, fullname)!=0) {
3601 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3605 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3614 /****************************************************************************
3615 The internals of the rmdir code - called elsewhere.
3616 ****************************************************************************/
3618 BOOL rmdir_internals(connection_struct *conn, char *directory)
3623 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3624 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3626 * Check to see if the only thing in this directory are
3627 * vetoed files/directories. If so then delete them and
3628 * retry. If we fail to delete any of them (and we *don't*
3629 * do a recursive delete) then fail the rmdir.
3631 BOOL all_veto_files = True;
3633 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3635 if(dir_hnd != NULL) {
3636 long dirpos = TellDir(dir_hnd);
3637 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3638 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3640 if (!is_visible_file(conn, directory, dname, &st, False))
3642 if(!IS_VETO_PATH(conn, dname)) {
3643 all_veto_files = False;
3648 if(all_veto_files) {
3649 SeekDir(dir_hnd,dirpos);
3650 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3653 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3655 if (!is_visible_file(conn, directory, dname, &st, False))
3658 /* Construct the full name. */
3659 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3664 pstrcpy(fullname, directory);
3665 pstrcat(fullname, "/");
3666 pstrcat(fullname, dname);
3668 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3670 if(st.st_mode & S_IFDIR) {
3671 if(lp_recursive_veto_delete(SNUM(conn))) {
3672 if(recursive_rmdir(conn, fullname) != 0)
3675 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3677 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3681 /* Retry the rmdir */
3682 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3692 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3697 /****************************************************************************
3699 ****************************************************************************/
3701 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3706 BOOL bad_path = False;
3707 SMB_STRUCT_STAT sbuf;
3709 START_PROFILE(SMBrmdir);
3711 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 END_PROFILE(SMBrmdir);
3714 return ERROR_NT(status);
3717 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3719 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3721 END_PROFILE(SMBrmdir);
3722 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3725 if (check_name(directory,conn)) {
3726 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3727 ok = rmdir_internals(conn, directory);
3731 END_PROFILE(SMBrmdir);
3732 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3735 outsize = set_message(outbuf,0,0,True);
3737 DEBUG( 3, ( "rmdir %s\n", directory ) );
3739 END_PROFILE(SMBrmdir);
3743 /*******************************************************************
3744 Resolve wildcards in a filename rename.
3745 Note that name is in UNIX charset and thus potentially can be more
3746 than fstring buffer (255 bytes) especially in default UTF-8 case.
3747 Therefore, we use pstring inside and all calls should ensure that
3748 name2 is at least pstring-long (they do already)
3749 ********************************************************************/
3751 static BOOL resolve_wildcards(const char *name1, char *name2)
3753 pstring root1,root2;
3755 char *p,*p2, *pname1, *pname2;
3756 int available_space, actual_space;
3759 pname1 = strrchr_m(name1,'/');
3760 pname2 = strrchr_m(name2,'/');
3762 if (!pname1 || !pname2)
3765 pstrcpy(root1,pname1);
3766 pstrcpy(root2,pname2);
3767 p = strrchr_m(root1,'.');
3774 p = strrchr_m(root2,'.');
3788 } else if (*p2 == '*') {
3804 } else if (*p2 == '*') {
3814 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3817 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3818 if (actual_space >= available_space - 1) {
3819 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3820 actual_space - available_space));
3823 pstrcpy_base(pname2, root2, name2);
3829 /****************************************************************************
3830 Ensure open files have their names updates.
3831 ****************************************************************************/
3833 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3836 BOOL did_rename = False;
3838 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3839 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3840 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3841 fsp->fsp_name, newname ));
3842 string_set(&fsp->fsp_name, newname);
3847 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3848 (unsigned int)dev, (double)inode, newname ));
3851 /****************************************************************************
3852 Rename an open file - given an fsp.
3853 ****************************************************************************/
3855 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3857 SMB_STRUCT_STAT sbuf;
3858 BOOL bad_path = False;
3859 pstring newname_last_component;
3860 NTSTATUS error = NT_STATUS_OK;
3865 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3867 /* Quick check for "." and ".." */
3868 if (!bad_path && newname_last_component[0] == '.') {
3869 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3870 return NT_STATUS_ACCESS_DENIED;
3873 if (!rcdest && bad_path) {
3874 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3877 /* Ensure newname contains a '/' */
3878 if(strrchr_m(newname,'/') == 0) {
3881 pstrcpy(tmpstr, "./");
3882 pstrcat(tmpstr, newname);
3883 pstrcpy(newname, tmpstr);
3887 * Check for special case with case preserving and not
3888 * case sensitive. If the old last component differs from the original
3889 * last component only by case, then we should allow
3890 * the rename (user is trying to change the case of the
3894 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3895 strequal(newname, fsp->fsp_name)) {
3897 pstring newname_modified_last_component;
3900 * Get the last component of the modified name.
3901 * Note that we guarantee that newname contains a '/'
3904 p = strrchr_m(newname,'/');
3905 pstrcpy(newname_modified_last_component,p+1);
3907 if(strcsequal(newname_modified_last_component,
3908 newname_last_component) == False) {
3910 * Replace the modified last component with
3913 pstrcpy(p+1, newname_last_component);
3918 * If the src and dest names are identical - including case,
3919 * don't do the rename, just return success.
3922 if (strcsequal(fsp->fsp_name, newname)) {
3923 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3925 return NT_STATUS_OK;
3928 dest_exists = vfs_object_exist(conn,newname,NULL);
3930 if(!replace_if_exists && dest_exists) {
3931 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3932 fsp->fsp_name,newname));
3933 return NT_STATUS_OBJECT_NAME_COLLISION;
3936 error = can_rename(conn,newname,attrs,&sbuf);
3938 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3939 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3940 nt_errstr(error), fsp->fsp_name,newname));
3941 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3942 error = NT_STATUS_ACCESS_DENIED;
3946 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3947 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3948 fsp->fsp_name,newname));
3949 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3950 return NT_STATUS_OK;
3953 if (errno == ENOTDIR || errno == EISDIR)
3954 error = NT_STATUS_OBJECT_NAME_COLLISION;
3956 error = map_nt_error_from_unix(errno);
3958 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3959 nt_errstr(error), fsp->fsp_name,newname));
3964 /****************************************************************************
3965 The guts of the rename command, split out so it may be called by the NT SMB
3967 ****************************************************************************/
3969 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3973 pstring last_component_src;
3974 pstring last_component_dest;
3977 BOOL bad_path_src = False;
3978 BOOL bad_path_dest = False;
3980 NTSTATUS error = NT_STATUS_OK;
3983 SMB_STRUCT_STAT sbuf1, sbuf2;
3985 *directory = *mask = 0;
3990 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3991 if (!rc && bad_path_src) {
3992 if (ms_has_wild(last_component_src))
3993 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3994 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3997 /* Quick check for "." and ".." */
3998 if (last_component_src[0] == '.') {
3999 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4000 return NT_STATUS_OBJECT_NAME_INVALID;
4004 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4006 /* Quick check for "." and ".." */
4007 if (last_component_dest[0] == '.') {
4008 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4009 return NT_STATUS_OBJECT_NAME_INVALID;
4014 * Split the old name into directory and last component
4015 * strings. Note that unix_convert may have stripped off a
4016 * leading ./ from both name and newname if the rename is
4017 * at the root of the share. We need to make sure either both
4018 * name and newname contain a / character or neither of them do
4019 * as this is checked in resolve_wildcards().
4022 p = strrchr_m(name,'/');
4024 pstrcpy(directory,".");
4028 pstrcpy(directory,name);
4030 *p = '/'; /* Replace needed for exceptional test below. */
4034 * We should only check the mangled cache
4035 * here if unix_convert failed. This means
4036 * that the path in 'mask' doesn't exist
4037 * on the file system and so we need to look
4038 * for a possible mangle. This patch from
4039 * Tine Smukavec <valentin.smukavec@hermes.si>.
4042 if (!rc && mangle_is_mangled(mask))
4043 mangle_check_cache( mask, sizeof(pstring)-1 );
4045 has_wild = ms_has_wild(mask);
4049 * No wildcards - just process the one file.
4051 BOOL is_short_name = mangle_is_8_3(name, True);
4053 /* Add a terminating '/' to the directory name. */
4054 pstrcat(directory,"/");
4055 pstrcat(directory,mask);
4057 /* Ensure newname contains a '/' also */
4058 if(strrchr_m(newname,'/') == 0) {
4061 pstrcpy(tmpstr, "./");
4062 pstrcat(tmpstr, newname);
4063 pstrcpy(newname, tmpstr);
4066 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4067 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4068 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4069 newname, last_component_dest, is_short_name));
4072 * Check for special case with case preserving and not
4073 * case sensitive, if directory and newname are identical,
4074 * and the old last component differs from the original
4075 * last component only by case, then we should allow
4076 * the rename (user is trying to change the case of the
4079 if((conn->case_sensitive == False) &&
4080 (((conn->case_preserve == True) &&
4081 (is_short_name == False)) ||
4082 ((conn->short_case_preserve == True) &&
4083 (is_short_name == True))) &&
4084 strcsequal(directory, newname)) {
4085 pstring modified_last_component;
4088 * Get the last component of the modified name.
4089 * Note that we guarantee that newname contains a '/'
4092 p = strrchr_m(newname,'/');
4093 pstrcpy(modified_last_component,p+1);
4095 if(strcsequal(modified_last_component,
4096 last_component_dest) == False) {
4098 * Replace the modified last component with
4101 pstrcpy(p+1, last_component_dest);
4105 resolve_wildcards(directory,newname);
4108 * The source object must exist.
4111 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4112 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4113 directory,newname));
4115 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4117 * Must return different errors depending on whether the parent
4118 * directory existed or not.
4121 p = strrchr_m(directory, '/');
4123 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4125 if (vfs_object_exist(conn, directory, NULL))
4126 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4127 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4129 error = map_nt_error_from_unix(errno);
4130 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4131 nt_errstr(error), directory,newname));
4136 if (!rcdest && bad_path_dest) {
4137 if (ms_has_wild(last_component_dest))
4138 return NT_STATUS_OBJECT_NAME_INVALID;
4139 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4142 error = can_rename(conn,directory,attrs,&sbuf1);
4144 if (!NT_STATUS_IS_OK(error)) {
4145 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4146 nt_errstr(error), directory,newname));
4151 * If the src and dest names are identical - including case,
4152 * don't do the rename, just return success.
4155 if (strcsequal(directory, newname)) {
4156 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4157 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4158 return NT_STATUS_OK;
4161 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4162 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4163 directory,newname));
4164 return NT_STATUS_OBJECT_NAME_COLLISION;
4167 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4168 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4169 directory,newname));
4170 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4171 return NT_STATUS_OK;
4174 if (errno == ENOTDIR || errno == EISDIR)
4175 error = NT_STATUS_OBJECT_NAME_COLLISION;
4177 error = map_nt_error_from_unix(errno);
4179 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4180 nt_errstr(error), directory,newname));
4185 * Wildcards - process each file that matches.
4187 struct smb_Dir *dir_hnd = NULL;
4191 if (check_name(directory,conn))
4192 dir_hnd = OpenDir(conn, directory);
4196 error = NT_STATUS_NO_SUCH_FILE;
4197 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4199 if (strequal(mask,"????????.???"))
4202 while ((dname = ReadDirName(dir_hnd, &offset))) {
4204 BOOL sysdir_entry = False;
4206 pstrcpy(fname,dname);
4208 /* Quick check for "." and ".." */
4209 if (fname[0] == '.') {
4210 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4212 sysdir_entry = True;
4219 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4222 if(!mask_match(fname, mask, conn->case_sensitive))
4226 error = NT_STATUS_OBJECT_NAME_INVALID;
4230 error = NT_STATUS_ACCESS_DENIED;
4231 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4232 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4233 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4234 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4237 error = can_rename(conn,fname,attrs,&sbuf1);
4238 if (!NT_STATUS_IS_OK(error)) {
4239 DEBUG(6,("rename %s refused\n", fname));
4242 pstrcpy(destname,newname);
4244 if (!resolve_wildcards(fname,destname)) {
4245 DEBUG(6,("resolve_wildcards %s %s failed\n",
4250 if (strcsequal(fname,destname)) {
4251 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4252 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4254 error = NT_STATUS_OK;
4258 if (!replace_if_exists &&
4259 vfs_file_exist(conn,destname, NULL)) {
4260 DEBUG(6,("file_exist %s\n", destname));
4261 error = NT_STATUS_OBJECT_NAME_COLLISION;
4265 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4266 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4268 error = NT_STATUS_OK;
4270 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4275 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4276 if (!rcdest && bad_path_dest) {
4277 if (ms_has_wild(last_component_dest))
4278 return NT_STATUS_OBJECT_NAME_INVALID;
4279 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4284 if (count == 0 && NT_STATUS_IS_OK(error)) {
4285 error = map_nt_error_from_unix(errno);
4291 /****************************************************************************
4293 ****************************************************************************/
4295 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4302 uint16 attrs = SVAL(inbuf,smb_vwv0);
4305 START_PROFILE(SMBmv);
4307 p = smb_buf(inbuf) + 1;
4308 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4309 if (!NT_STATUS_IS_OK(status)) {
4311 return ERROR_NT(status);
4314 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4315 if (!NT_STATUS_IS_OK(status)) {
4317 return ERROR_NT(status);
4320 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4321 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4323 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4325 status = rename_internals(conn, name, newname, attrs, False);
4326 if (!NT_STATUS_IS_OK(status)) {
4328 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4329 /* We have re-scheduled this call. */
4332 return ERROR_NT(status);
4336 * Win2k needs a changenotify request response before it will
4337 * update after a rename..
4339 process_pending_change_notify_queue((time_t)0);
4340 outsize = set_message(outbuf,0,0,True);
4346 /*******************************************************************
4347 Copy a file as part of a reply_copy.
4348 ******************************************************************/
4350 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4351 int count,BOOL target_is_directory, int *err_ret)
4354 SMB_STRUCT_STAT src_sbuf, sbuf2;
4356 files_struct *fsp1,*fsp2;
4362 pstrcpy(dest,dest1);
4363 if (target_is_directory) {
4364 char *p = strrchr_m(src,'/');
4373 if (!vfs_file_exist(conn,src,&src_sbuf))
4376 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4377 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4383 if (!target_is_directory && count)
4384 ofun = FILE_EXISTS_OPEN;
4386 dosattrs = dos_mode(conn, src, &src_sbuf);
4387 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4388 ZERO_STRUCTP(&sbuf2);
4390 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4391 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4394 close_file(fsp1,False);
4398 if ((ofun&3) == 1) {
4399 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4400 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4402 * Stop the copy from occurring.
4405 src_sbuf.st_size = 0;
4409 if (src_sbuf.st_size)
4410 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4412 close_file(fsp1,False);
4414 /* Ensure the modtime is set correctly on the destination file. */
4415 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4418 * As we are opening fsp1 read-only we only expect
4419 * an error on close on fsp2 if we are out of space.
4420 * Thus we don't look at the error return from the
4423 *err_ret = close_file(fsp2,False);
4425 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4428 /****************************************************************************
4429 Reply to a file copy.
4430 ****************************************************************************/
4432 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4437 pstring mask,newname;
4440 int error = ERRnoaccess;
4444 int tid2 = SVAL(inbuf,smb_vwv0);
4445 int ofun = SVAL(inbuf,smb_vwv1);
4446 int flags = SVAL(inbuf,smb_vwv2);
4447 BOOL target_is_directory=False;
4448 BOOL bad_path1 = False;
4449 BOOL bad_path2 = False;
4451 SMB_STRUCT_STAT sbuf1, sbuf2;
4454 START_PROFILE(SMBcopy);
4456 *directory = *mask = 0;
4459 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4460 if (!NT_STATUS_IS_OK(status)) {
4461 END_PROFILE(SMBcopy);
4462 return ERROR_NT(status);
4464 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4465 if (!NT_STATUS_IS_OK(status)) {
4466 END_PROFILE(SMBcopy);
4467 return ERROR_NT(status);
4470 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4472 if (tid2 != conn->cnum) {
4473 /* can't currently handle inter share copies XXXX */
4474 DEBUG(3,("Rejecting inter-share copy\n"));
4475 END_PROFILE(SMBcopy);
4476 return ERROR_DOS(ERRSRV,ERRinvdevice);
4479 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4480 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4482 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4483 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4485 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4487 if ((flags&1) && target_is_directory) {
4488 END_PROFILE(SMBcopy);
4489 return ERROR_DOS(ERRDOS,ERRbadfile);
4492 if ((flags&2) && !target_is_directory) {
4493 END_PROFILE(SMBcopy);
4494 return ERROR_DOS(ERRDOS,ERRbadpath);
4497 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4498 /* wants a tree copy! XXXX */
4499 DEBUG(3,("Rejecting tree copy\n"));
4500 END_PROFILE(SMBcopy);
4501 return ERROR_DOS(ERRSRV,ERRerror);
4504 p = strrchr_m(name,'/');
4506 pstrcpy(directory,"./");
4510 pstrcpy(directory,name);
4515 * We should only check the mangled cache
4516 * here if unix_convert failed. This means
4517 * that the path in 'mask' doesn't exist
4518 * on the file system and so we need to look
4519 * for a possible mangle. This patch from
4520 * Tine Smukavec <valentin.smukavec@hermes.si>.
4523 if (!rc && mangle_is_mangled(mask))
4524 mangle_check_cache( mask, sizeof(pstring)-1 );
4526 has_wild = ms_has_wild(mask);
4529 pstrcat(directory,"/");
4530 pstrcat(directory,mask);
4531 if (resolve_wildcards(directory,newname) &&
4532 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4536 END_PROFILE(SMBcopy);
4537 return(UNIXERROR(ERRHRD,ERRgeneral));
4540 exists = vfs_file_exist(conn,directory,NULL);
4543 struct smb_Dir *dir_hnd = NULL;
4547 if (check_name(directory,conn))
4548 dir_hnd = OpenDir(conn, directory);
4554 if (strequal(mask,"????????.???"))
4557 while ((dname = ReadDirName(dir_hnd, &offset))) {
4559 pstrcpy(fname,dname);
4561 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4564 if(!mask_match(fname, mask, conn->case_sensitive))
4567 error = ERRnoaccess;
4568 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4569 pstrcpy(destname,newname);
4570 if (resolve_wildcards(fname,destname) &&
4571 copy_file(fname,destname,conn,ofun,
4572 count,target_is_directory,&err))
4574 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4582 /* Error on close... */
4584 END_PROFILE(SMBcopy);
4585 return(UNIXERROR(ERRHRD,ERRgeneral));
4589 END_PROFILE(SMBcopy);
4590 return ERROR_DOS(ERRDOS,error);
4592 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4593 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4595 END_PROFILE(SMBcopy);
4596 return(UNIXERROR(ERRDOS,error));
4600 outsize = set_message(outbuf,1,0,True);
4601 SSVAL(outbuf,smb_vwv0,count);
4603 END_PROFILE(SMBcopy);
4607 /****************************************************************************
4609 ****************************************************************************/
4611 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4619 START_PROFILE(pathworks_setdir);
4622 if (!CAN_SETDIR(snum)) {
4623 END_PROFILE(pathworks_setdir);
4624 return ERROR_DOS(ERRDOS,ERRnoaccess);
4627 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4628 if (!NT_STATUS_IS_OK(status)) {
4629 END_PROFILE(pathworks_setdir);
4630 return ERROR_NT(status);
4633 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4635 if (strlen(newdir) == 0) {
4638 ok = vfs_directory_exist(conn,newdir,NULL);
4640 string_set(&conn->connectpath,newdir);
4644 END_PROFILE(pathworks_setdir);
4645 return ERROR_DOS(ERRDOS,ERRbadpath);
4648 outsize = set_message(outbuf,0,0,True);
4649 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4651 DEBUG(3,("setdir %s\n", newdir));
4653 END_PROFILE(pathworks_setdir);
4657 /****************************************************************************
4658 Get a lock pid, dealing with large count requests.
4659 ****************************************************************************/
4661 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4663 if(!large_file_format)
4664 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4666 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4669 /****************************************************************************
4670 Get a lock count, dealing with large count requests.
4671 ****************************************************************************/
4673 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4675 SMB_BIG_UINT count = 0;
4677 if(!large_file_format) {
4678 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4681 #if defined(HAVE_LONGLONG)
4682 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4683 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4684 #else /* HAVE_LONGLONG */
4687 * NT4.x seems to be broken in that it sends large file (64 bit)
4688 * lockingX calls even if the CAP_LARGE_FILES was *not*
4689 * negotiated. For boxes without large unsigned ints truncate the
4690 * lock count by dropping the top 32 bits.
4693 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4694 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4695 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4696 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4697 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4700 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4701 #endif /* HAVE_LONGLONG */
4707 #if !defined(HAVE_LONGLONG)
4708 /****************************************************************************
4709 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4710 ****************************************************************************/
4712 static uint32 map_lock_offset(uint32 high, uint32 low)
4716 uint32 highcopy = high;
4719 * Try and find out how many significant bits there are in high.
4722 for(i = 0; highcopy; i++)
4726 * We use 31 bits not 32 here as POSIX
4727 * lock offsets may not be negative.
4730 mask = (~0) << (31 - i);
4733 return 0; /* Fail. */
4739 #endif /* !defined(HAVE_LONGLONG) */
4741 /****************************************************************************
4742 Get a lock offset, dealing with large offset requests.
4743 ****************************************************************************/
4745 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4747 SMB_BIG_UINT offset = 0;
4751 if(!large_file_format) {
4752 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4755 #if defined(HAVE_LONGLONG)
4756 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4757 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4758 #else /* HAVE_LONGLONG */
4761 * NT4.x seems to be broken in that it sends large file (64 bit)
4762 * lockingX calls even if the CAP_LARGE_FILES was *not*
4763 * negotiated. For boxes without large unsigned ints mangle the
4764 * lock offset by mapping the top 32 bits onto the lower 32.
4767 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4768 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4769 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4772 if((new_low = map_lock_offset(high, low)) == 0) {
4774 return (SMB_BIG_UINT)-1;
4777 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4778 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4779 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4780 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4783 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4784 #endif /* HAVE_LONGLONG */
4790 /****************************************************************************
4791 Reply to a lockingX request.
4792 ****************************************************************************/
4794 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4796 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4797 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4798 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4799 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4800 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4801 SMB_BIG_UINT count = 0, offset = 0;
4803 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4806 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4808 BOOL my_lock_ctx = False;
4811 START_PROFILE(SMBlockingX);
4813 CHECK_FSP(fsp,conn);
4815 data = smb_buf(inbuf);
4817 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4818 /* we don't support these - and CANCEL_LOCK makes w2k
4819 and XP reboot so I don't really want to be
4820 compatible! (tridge) */
4821 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4824 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4825 /* Need to make this like a cancel.... JRA. */
4826 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4829 /* Check if this is an oplock break on a file
4830 we have granted an oplock on.
4832 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4833 /* Client can insist on breaking to none. */
4834 BOOL break_to_none = (oplocklevel == 0);
4836 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4837 (unsigned int)oplocklevel, fsp->fnum ));
4840 * Make sure we have granted an exclusive or batch oplock on this file.
4843 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4844 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4845 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4847 /* if this is a pure oplock break request then don't send a reply */
4848 if (num_locks == 0 && num_ulocks == 0) {
4849 END_PROFILE(SMBlockingX);
4852 END_PROFILE(SMBlockingX);
4853 return ERROR_DOS(ERRDOS,ERRlock);
4857 if (remove_oplock(fsp, break_to_none) == False) {
4858 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4862 /* if this is a pure oplock break request then don't send a reply */
4863 if (num_locks == 0 && num_ulocks == 0) {
4864 /* Sanity check - ensure a pure oplock break is not a
4866 if(CVAL(inbuf,smb_vwv0) != 0xff)
4867 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4868 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4869 END_PROFILE(SMBlockingX);
4875 * We do this check *after* we have checked this is not a oplock break
4876 * response message. JRA.
4879 release_level_2_oplocks_on_change(fsp);
4881 /* Data now points at the beginning of the list
4882 of smb_unlkrng structs */
4883 for(i = 0; i < (int)num_ulocks; i++) {
4884 lock_pid = get_lock_pid( data, i, large_file_format);
4885 count = get_lock_count( data, i, large_file_format);
4886 offset = get_lock_offset( data, i, large_file_format, &err);
4889 * There is no error code marked "stupid client bug".... :-).
4892 END_PROFILE(SMBlockingX);
4893 return ERROR_DOS(ERRDOS,ERRnoaccess);
4896 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4897 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4899 status = do_unlock(fsp,conn,lock_pid,count,offset);
4900 if (NT_STATUS_V(status)) {
4901 END_PROFILE(SMBlockingX);
4902 return ERROR_NT(status);
4906 /* Setup the timeout in seconds. */
4908 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4910 /* Now do any requested locks */
4911 data += ((large_file_format ? 20 : 10)*num_ulocks);
4913 /* Data now points at the beginning of the list
4914 of smb_lkrng structs */
4916 for(i = 0; i < (int)num_locks; i++) {
4917 lock_pid = get_lock_pid( data, i, large_file_format);
4918 count = get_lock_count( data, i, large_file_format);
4919 offset = get_lock_offset( data, i, large_file_format, &err);
4922 * There is no error code marked "stupid client bug".... :-).
4925 END_PROFILE(SMBlockingX);
4926 return ERROR_DOS(ERRDOS,ERRnoaccess);
4929 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4930 (double)offset, (double)count, (unsigned int)lock_pid,
4931 fsp->fsp_name, (int)lock_timeout ));
4933 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4934 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4935 if (NT_STATUS_V(status)) {
4937 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4938 * Even if it's our own lock context, we need to wait here as
4939 * there may be an unlock on the way.
4940 * So I removed a "&& !my_lock_ctx" from the following
4941 * if statement. JRA.
4943 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4945 * A blocking lock was requested. Package up
4946 * this smb into a queued request and push it
4947 * onto the blocking lock queue.
4949 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4950 END_PROFILE(SMBlockingX);
4958 /* If any of the above locks failed, then we must unlock
4959 all of the previous locks (X/Open spec). */
4960 if (i != num_locks && num_locks != 0) {
4962 * Ensure we don't do a remove on the lock that just failed,
4963 * as under POSIX rules, if we have a lock already there, we
4964 * will delete it (and we shouldn't) .....
4966 for(i--; i >= 0; i--) {
4967 lock_pid = get_lock_pid( data, i, large_file_format);
4968 count = get_lock_count( data, i, large_file_format);
4969 offset = get_lock_offset( data, i, large_file_format, &err);
4972 * There is no error code marked "stupid client bug".... :-).
4975 END_PROFILE(SMBlockingX);
4976 return ERROR_DOS(ERRDOS,ERRnoaccess);
4979 do_unlock(fsp,conn,lock_pid,count,offset);
4981 END_PROFILE(SMBlockingX);
4982 return ERROR_NT(status);
4985 set_message(outbuf,2,0,True);
4987 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4988 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4990 END_PROFILE(SMBlockingX);
4991 return chain_reply(inbuf,outbuf,length,bufsize);
4994 /****************************************************************************
4995 Reply to a SMBreadbmpx (read block multiplex) request.
4996 ****************************************************************************/
4998 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5009 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5010 START_PROFILE(SMBreadBmpx);
5012 /* this function doesn't seem to work - disable by default */
5013 if (!lp_readbmpx()) {
5014 END_PROFILE(SMBreadBmpx);
5015 return ERROR_DOS(ERRSRV,ERRuseSTD);
5018 outsize = set_message(outbuf,8,0,True);
5020 CHECK_FSP(fsp,conn);
5023 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5024 maxcount = SVAL(inbuf,smb_vwv3);
5026 data = smb_buf(outbuf);
5027 pad = ((long)data)%4;
5032 max_per_packet = bufsize-(outsize+pad);
5036 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5037 END_PROFILE(SMBreadBmpx);
5038 return ERROR_DOS(ERRDOS,ERRlock);
5042 size_t N = MIN(max_per_packet,tcount-total_read);
5044 nread = read_file(fsp,data,startpos,N);
5049 if (nread < (ssize_t)N)
5050 tcount = total_read + nread;
5052 set_message(outbuf,8,nread,False);
5053 SIVAL(outbuf,smb_vwv0,startpos);
5054 SSVAL(outbuf,smb_vwv2,tcount);
5055 SSVAL(outbuf,smb_vwv6,nread);
5056 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5058 if (!send_smb(smbd_server_fd(),outbuf))
5059 exit_server("reply_readbmpx: send_smb failed.");
5061 total_read += nread;
5063 } while (total_read < (ssize_t)tcount);
5065 END_PROFILE(SMBreadBmpx);
5069 /****************************************************************************
5070 Reply to a SMBsetattrE.
5071 ****************************************************************************/
5073 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5075 struct utimbuf unix_times;
5077 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5078 START_PROFILE(SMBsetattrE);
5080 outsize = set_message(outbuf,0,0,True);
5082 if(!fsp || (fsp->conn != conn)) {
5083 END_PROFILE(SMBgetattrE);
5084 return ERROR_DOS(ERRDOS,ERRbadfid);
5088 * Convert the DOS times into unix times. Ignore create
5089 * time as UNIX can't set this.
5092 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5093 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5096 * Patch from Ray Frush <frush@engr.colostate.edu>
5097 * Sometimes times are sent as zero - ignore them.
5100 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5101 /* Ignore request */
5102 if( DEBUGLVL( 3 ) ) {
5103 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5104 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5106 END_PROFILE(SMBsetattrE);
5108 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5109 /* set modify time = to access time if modify time was unset */
5110 unix_times.modtime = unix_times.actime;
5113 /* Set the date on this file */
5114 /* Should we set pending modtime here ? JRA */
5115 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5116 END_PROFILE(SMBsetattrE);
5117 return ERROR_DOS(ERRDOS,ERRnoaccess);
5120 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5121 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5123 END_PROFILE(SMBsetattrE);
5128 /* Back from the dead for OS/2..... JRA. */
5130 /****************************************************************************
5131 Reply to a SMBwritebmpx (write block multiplex primary) request.
5132 ****************************************************************************/
5134 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5137 ssize_t nwritten = -1;
5144 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5145 START_PROFILE(SMBwriteBmpx);
5147 CHECK_FSP(fsp,conn);
5149 if (HAS_CACHED_ERROR(fsp)) {
5150 return(CACHED_ERROR(fsp));
5153 tcount = SVAL(inbuf,smb_vwv1);
5154 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5155 write_through = BITSETW(inbuf+smb_vwv7,0);
5156 numtowrite = SVAL(inbuf,smb_vwv10);
5157 smb_doff = SVAL(inbuf,smb_vwv11);
5159 data = smb_base(inbuf) + smb_doff;
5161 /* If this fails we need to send an SMBwriteC response,
5162 not an SMBwritebmpx - set this up now so we don't forget */
5163 SCVAL(outbuf,smb_com,SMBwritec);
5165 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5166 END_PROFILE(SMBwriteBmpx);
5167 return(ERROR_DOS(ERRDOS,ERRlock));
5170 nwritten = write_file(fsp,data,startpos,numtowrite);
5172 if(lp_syncalways(SNUM(conn)) || write_through)
5173 sync_file(conn,fsp);
5175 if(nwritten < (ssize_t)numtowrite) {
5176 END_PROFILE(SMBwriteBmpx);
5177 return(UNIXERROR(ERRHRD,ERRdiskfull));
5180 /* If the maximum to be written to this file
5181 is greater than what we just wrote then set
5182 up a secondary struct to be attached to this
5183 fd, we will use this to cache error messages etc. */
5185 if((ssize_t)tcount > nwritten) {
5186 write_bmpx_struct *wbms;
5187 if(fsp->wbmpx_ptr != NULL)
5188 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5190 wbms = SMB_MALLOC_P(write_bmpx_struct);
5192 DEBUG(0,("Out of memory in reply_readmpx\n"));
5193 END_PROFILE(SMBwriteBmpx);
5194 return(ERROR_DOS(ERRSRV,ERRnoresource));
5196 wbms->wr_mode = write_through;
5197 wbms->wr_discard = False; /* No errors yet */
5198 wbms->wr_total_written = nwritten;
5199 wbms->wr_errclass = 0;
5201 fsp->wbmpx_ptr = wbms;
5204 /* We are returning successfully, set the message type back to
5206 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5208 outsize = set_message(outbuf,1,0,True);
5210 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5212 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5213 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5215 if (write_through && tcount==nwritten) {
5216 /* We need to send both a primary and a secondary response */
5217 smb_setlen(outbuf,outsize - 4);
5218 if (!send_smb(smbd_server_fd(),outbuf))
5219 exit_server("reply_writebmpx: send_smb failed.");
5221 /* Now the secondary */
5222 outsize = set_message(outbuf,1,0,True);
5223 SCVAL(outbuf,smb_com,SMBwritec);
5224 SSVAL(outbuf,smb_vwv0,nwritten);
5227 END_PROFILE(SMBwriteBmpx);
5231 /****************************************************************************
5232 Reply to a SMBwritebs (write block multiplex secondary) request.
5233 ****************************************************************************/
5235 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5238 ssize_t nwritten = -1;
5245 write_bmpx_struct *wbms;
5246 BOOL send_response = False;
5247 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5248 START_PROFILE(SMBwriteBs);
5250 CHECK_FSP(fsp,conn);
5253 tcount = SVAL(inbuf,smb_vwv1);
5254 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5255 numtowrite = SVAL(inbuf,smb_vwv6);
5256 smb_doff = SVAL(inbuf,smb_vwv7);
5258 data = smb_base(inbuf) + smb_doff;
5260 /* We need to send an SMBwriteC response, not an SMBwritebs */
5261 SCVAL(outbuf,smb_com,SMBwritec);
5263 /* This fd should have an auxiliary struct attached,
5264 check that it does */
5265 wbms = fsp->wbmpx_ptr;
5267 END_PROFILE(SMBwriteBs);
5271 /* If write through is set we can return errors, else we must cache them */
5272 write_through = wbms->wr_mode;
5274 /* Check for an earlier error */
5275 if(wbms->wr_discard) {
5276 END_PROFILE(SMBwriteBs);
5277 return -1; /* Just discard the packet */
5280 nwritten = write_file(fsp,data,startpos,numtowrite);
5282 if(lp_syncalways(SNUM(conn)) || write_through)
5283 sync_file(conn,fsp);
5285 if (nwritten < (ssize_t)numtowrite) {
5287 /* We are returning an error - we can delete the aux struct */
5290 fsp->wbmpx_ptr = NULL;
5291 END_PROFILE(SMBwriteBs);
5292 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5294 wbms->wr_errclass = ERRHRD;
5295 wbms->wr_error = ERRdiskfull;
5296 wbms->wr_status = NT_STATUS_DISK_FULL;
5297 wbms->wr_discard = True;
5298 END_PROFILE(SMBwriteBs);
5302 /* Increment the total written, if this matches tcount
5303 we can discard the auxiliary struct (hurrah !) and return a writeC */
5304 wbms->wr_total_written += nwritten;
5305 if(wbms->wr_total_written >= tcount) {
5306 if (write_through) {
5307 outsize = set_message(outbuf,1,0,True);
5308 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5309 send_response = True;
5313 fsp->wbmpx_ptr = NULL;
5317 END_PROFILE(SMBwriteBs);
5321 END_PROFILE(SMBwriteBs);
5325 /****************************************************************************
5326 Reply to a SMBgetattrE.
5327 ****************************************************************************/
5329 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5331 SMB_STRUCT_STAT sbuf;
5334 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5335 START_PROFILE(SMBgetattrE);
5337 outsize = set_message(outbuf,11,0,True);
5339 if(!fsp || (fsp->conn != conn)) {
5340 END_PROFILE(SMBgetattrE);
5341 return ERROR_DOS(ERRDOS,ERRbadfid);
5344 /* Do an fstat on this file */
5345 if(fsp_stat(fsp, &sbuf)) {
5346 END_PROFILE(SMBgetattrE);
5347 return(UNIXERROR(ERRDOS,ERRnoaccess));
5350 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5353 * Convert the times into dos times. Set create
5354 * date to be last modify date as UNIX doesn't save
5358 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5359 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5360 /* Should we check pending modtime here ? JRA */
5361 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5364 SIVAL(outbuf,smb_vwv6,0);
5365 SIVAL(outbuf,smb_vwv8,0);
5367 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5368 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5369 SIVAL(outbuf,smb_vwv8,allocation_size);
5371 SSVAL(outbuf,smb_vwv10, mode);
5373 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5375 END_PROFILE(SMBgetattrE);