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 START_PROFILE(SMBopenX);
1273 /* If it's an IPC, pass off the pipe handler. */
1275 if (lp_nt_pipe_support()) {
1276 END_PROFILE(SMBopenX);
1277 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1279 END_PROFILE(SMBopenX);
1280 return ERROR_DOS(ERRSRV,ERRaccess);
1284 /* XXXX we need to handle passed times, sattr and flags */
1285 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 END_PROFILE(SMBopenX);
1288 return ERROR_NT(status);
1291 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1293 unix_convert(fname,conn,0,&bad_path,&sbuf);
1295 END_PROFILE(SMBopenX);
1296 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1299 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1300 oplock_request, &rmode,&smb_action);
1303 END_PROFILE(SMBopenX);
1304 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1305 /* We have re-scheduled this call. */
1308 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1311 size = sbuf.st_size;
1313 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
1314 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1315 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
1316 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1317 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1318 close_file(fsp,False);
1319 END_PROFILE(SMBntcreateX);
1320 return ERROR_NT(NT_STATUS_DISK_FULL);
1323 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
1327 fmode = dos_mode(conn,fname,&sbuf);
1328 mtime = sbuf.st_mtime;
1330 close_file(fsp,False);
1331 END_PROFILE(SMBopenX);
1332 return ERROR_DOS(ERRDOS,ERRnoaccess);
1335 /* If the caller set the extended oplock request bit
1336 and we granted one (by whatever means) - set the
1337 correct bit for extended oplock reply.
1340 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1341 smb_action |= EXTENDED_OPLOCK_GRANTED;
1343 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1344 smb_action |= EXTENDED_OPLOCK_GRANTED;
1346 /* If the caller set the core oplock request bit
1347 and we granted one (by whatever means) - set the
1348 correct bit for core oplock reply.
1351 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1352 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1354 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1355 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1357 set_message(outbuf,15,0,True);
1358 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1359 SSVAL(outbuf,smb_vwv3,fmode);
1360 if(lp_dos_filetime_resolution(SNUM(conn)) )
1361 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1363 put_dos_date3(outbuf,smb_vwv4,mtime);
1364 SIVAL(outbuf,smb_vwv6,(uint32)get_allocation_size(conn,fsp,&sbuf));
1365 SSVAL(outbuf,smb_vwv8,rmode);
1366 SSVAL(outbuf,smb_vwv11,smb_action);
1368 END_PROFILE(SMBopenX);
1369 return chain_reply(inbuf,outbuf,length,bufsize);
1372 /****************************************************************************
1373 Reply to a SMBulogoffX.
1374 ****************************************************************************/
1376 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1378 uint16 vuid = SVAL(inbuf,smb_uid);
1379 user_struct *vuser = get_valid_user_struct(vuid);
1380 START_PROFILE(SMBulogoffX);
1383 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1385 /* in user level security we are supposed to close any files
1386 open by this user */
1387 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1388 file_close_user(vuid);
1390 invalidate_vuid(vuid);
1392 set_message(outbuf,2,0,True);
1394 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1396 END_PROFILE(SMBulogoffX);
1397 return chain_reply(inbuf,outbuf,length,bufsize);
1400 /****************************************************************************
1401 Reply to a mknew or a create.
1402 ****************************************************************************/
1404 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1411 BOOL bad_path = False;
1413 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1414 SMB_STRUCT_STAT sbuf;
1416 START_PROFILE(SMBcreate);
1418 com = SVAL(inbuf,smb_com);
1420 createmode = SVAL(inbuf,smb_vwv0);
1421 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 END_PROFILE(SMBcreate);
1424 return ERROR_NT(status);
1427 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1429 unix_convert(fname,conn,0,&bad_path,&sbuf);
1431 END_PROFILE(SMBcreate);
1432 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1435 if (createmode & aVOLID)
1436 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1438 if(com == SMBmknew) {
1439 /* We should fail if file exists. */
1440 ofun = FILE_CREATE_IF_NOT_EXIST;
1442 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1443 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1446 /* Open file in dos compatibility share mode. */
1447 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1448 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1451 END_PROFILE(SMBcreate);
1452 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1453 /* We have re-scheduled this call. */
1456 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1459 outsize = set_message(outbuf,1,0,True);
1460 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1462 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1463 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1465 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1466 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1468 DEBUG( 2, ( "new file %s\n", fname ) );
1469 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1471 END_PROFILE(SMBcreate);
1475 /****************************************************************************
1476 Reply to a create temporary file.
1477 ****************************************************************************/
1479 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1484 BOOL bad_path = False;
1486 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1488 SMB_STRUCT_STAT sbuf;
1491 unsigned int namelen;
1493 START_PROFILE(SMBctemp);
1495 createattr = SVAL(inbuf,smb_vwv0);
1496 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 END_PROFILE(SMBctemp);
1499 return ERROR_NT(status);
1502 pstrcat(fname,"/TMXXXXXX");
1504 pstrcat(fname,"TMXXXXXX");
1507 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1509 unix_convert(fname,conn,0,&bad_path,&sbuf);
1511 END_PROFILE(SMBctemp);
1512 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1515 tmpfd = smb_mkstemp(fname);
1517 END_PROFILE(SMBctemp);
1518 return(UNIXERROR(ERRDOS,ERRnoaccess));
1521 SMB_VFS_STAT(conn,fname,&sbuf);
1523 /* Open file in dos compatibility share mode. */
1524 /* We should fail if file does not exist. */
1525 fsp = open_file_shared(conn,fname,&sbuf,
1526 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1527 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1528 (uint32)createattr, oplock_request, NULL, NULL);
1530 /* close fd from smb_mkstemp() */
1534 END_PROFILE(SMBctemp);
1535 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1536 /* We have re-scheduled this call. */
1539 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1542 outsize = set_message(outbuf,1,0,True);
1543 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1545 /* the returned filename is relative to the directory */
1546 s = strrchr_m(fname, '/');
1552 p = smb_buf(outbuf);
1554 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1555 thing in the byte section. JRA */
1556 SSVALS(p, 0, -1); /* what is this? not in spec */
1558 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1560 outsize = set_message_end(outbuf, p);
1562 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1563 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1565 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1566 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1568 DEBUG( 2, ( "created temp file %s\n", fname ) );
1569 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1570 fname, fsp->fd, sbuf.st_mode ) );
1572 END_PROFILE(SMBctemp);
1576 /*******************************************************************
1577 Check if a user is allowed to rename a file.
1578 ********************************************************************/
1580 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1587 if (!CAN_WRITE(conn))
1588 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1590 fmode = dos_mode(conn,fname,pst);
1591 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1592 return NT_STATUS_NO_SUCH_FILE;
1594 if (S_ISDIR(pst->st_mode))
1595 return NT_STATUS_OK;
1597 /* We need a better way to return NT status codes from open... */
1598 set_saved_error_triple(0, 0, NT_STATUS_OK);
1600 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1601 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1605 if (get_saved_error_triple(NULL, NULL, &ret)) {
1606 set_saved_error_triple(0, 0, NT_STATUS_OK);
1609 set_saved_error_triple(0, 0, NT_STATUS_OK);
1610 return NT_STATUS_ACCESS_DENIED;
1612 close_file(fsp,False);
1613 return NT_STATUS_OK;
1616 /*******************************************************************
1617 Check if a user is allowed to delete a file.
1618 ********************************************************************/
1620 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1622 SMB_STRUCT_STAT sbuf;
1628 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1631 if (!CAN_WRITE(conn))
1632 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1634 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1635 if(errno == ENOENT) {
1637 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1639 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1641 return map_nt_error_from_unix(errno);
1644 fmode = dos_mode(conn,fname,&sbuf);
1646 /* Can't delete a directory. */
1648 return NT_STATUS_FILE_IS_A_DIRECTORY;
1650 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1651 return NT_STATUS_OBJECT_NAME_INVALID;
1652 #endif /* JRATEST */
1654 if (!lp_delete_readonly(SNUM(conn))) {
1656 return NT_STATUS_CANNOT_DELETE;
1658 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1659 return NT_STATUS_NO_SUCH_FILE;
1661 if (check_is_at_open) {
1662 if (!can_delete_file_in_directory(conn, fname)) {
1663 return NT_STATUS_ACCESS_DENIED;
1666 /* On open checks the open itself will check the share mode, so
1667 don't do it here as we'll get it wrong. */
1669 /* We need a better way to return NT status codes from open... */
1670 set_saved_error_triple(0, 0, NT_STATUS_OK);
1672 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1673 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1677 if (get_saved_error_triple(NULL, NULL, &ret)) {
1678 set_saved_error_triple(0, 0, NT_STATUS_OK);
1681 set_saved_error_triple(0, 0, NT_STATUS_OK);
1682 return NT_STATUS_ACCESS_DENIED;
1684 close_file(fsp,False);
1686 return NT_STATUS_OK;
1689 /****************************************************************************
1690 The guts of the unlink command, split out so it may be called by the NT SMB
1692 ****************************************************************************/
1694 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1700 NTSTATUS error = NT_STATUS_OK;
1702 BOOL bad_path = False;
1704 SMB_STRUCT_STAT sbuf;
1706 *directory = *mask = 0;
1708 /* We must check for wildcards in the name given
1709 * directly by the client - before any unmangling.
1710 * This prevents an unmangling of a UNIX name containing
1711 * a DOS wildcard like '*' or '?' from unmangling into
1712 * a wildcard delete which was not intended.
1713 * FIX for #226. JRA.
1716 has_wild = ms_has_wild(name);
1718 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1720 p = strrchr_m(name,'/');
1722 pstrcpy(directory,".");
1726 pstrcpy(directory,name);
1731 * We should only check the mangled cache
1732 * here if unix_convert failed. This means
1733 * that the path in 'mask' doesn't exist
1734 * on the file system and so we need to look
1735 * for a possible mangle. This patch from
1736 * Tine Smukavec <valentin.smukavec@hermes.si>.
1739 if (!rc && mangle_is_mangled(mask))
1740 mangle_check_cache( mask, sizeof(pstring)-1 );
1743 pstrcat(directory,"/");
1744 pstrcat(directory,mask);
1745 error = can_delete(conn,directory,dirtype,bad_path,False);
1746 if (!NT_STATUS_IS_OK(error))
1749 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1753 struct smb_Dir *dir_hnd = NULL;
1756 if (check_name(directory,conn))
1757 dir_hnd = OpenDir(conn, directory);
1759 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1760 the pattern matches against the long name, otherwise the short name
1761 We don't implement this yet XXXX
1766 error = NT_STATUS_NO_SUCH_FILE;
1768 if (strequal(mask,"????????.???"))
1771 while ((dname = ReadDirName(dir_hnd, &offset))) {
1774 BOOL sys_direntry = False;
1775 pstrcpy(fname,dname);
1777 if (!is_visible_file(conn, directory, dname, &st, True)) {
1781 /* Quick check for "." and ".." */
1782 if (fname[0] == '.') {
1783 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1784 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1785 sys_direntry = True;
1792 if(!mask_match(fname, mask, conn->case_sensitive))
1796 error = NT_STATUS_OBJECT_NAME_INVALID;
1797 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1802 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1803 error = can_delete(conn,fname,dirtype,bad_path,False);
1804 if (!NT_STATUS_IS_OK(error)) {
1807 if (SMB_VFS_UNLINK(conn,fname) == 0)
1809 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1815 if (count == 0 && NT_STATUS_IS_OK(error)) {
1816 error = map_nt_error_from_unix(errno);
1822 /****************************************************************************
1824 ****************************************************************************/
1826 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1833 START_PROFILE(SMBunlink);
1835 dirtype = SVAL(inbuf,smb_vwv0);
1837 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1838 if (!NT_STATUS_IS_OK(status)) {
1839 END_PROFILE(SMBunlink);
1840 return ERROR_NT(status);
1843 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1845 DEBUG(3,("reply_unlink : %s\n",name));
1847 status = unlink_internals(conn, dirtype, name);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1850 /* We have re-scheduled this call. */
1853 return ERROR_NT(status);
1857 * Win2k needs a changenotify request response before it will
1858 * update after a rename..
1860 process_pending_change_notify_queue((time_t)0);
1862 outsize = set_message(outbuf,0,0,True);
1864 END_PROFILE(SMBunlink);
1868 /****************************************************************************
1870 ****************************************************************************/
1872 static void fail_readraw(void)
1875 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1877 exit_server(errstr);
1880 #if defined(WITH_SENDFILE)
1881 /****************************************************************************
1882 Fake (read/write) sendfile. Returns -1 on read or write fail.
1883 ****************************************************************************/
1885 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1889 /* Paranioa check... */
1890 if (nread > bufsize) {
1895 ret = read_file(fsp,buf,startpos,nread);
1901 /* If we had a short read, fill with zeros. */
1903 memset(buf, '\0', nread - ret);
1906 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1910 return (ssize_t)nread;
1914 /****************************************************************************
1915 Use sendfile in readbraw.
1916 ****************************************************************************/
1918 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1919 ssize_t mincount, char *outbuf, int out_buffsize)
1923 #if defined(WITH_SENDFILE)
1925 * We can only use sendfile on a non-chained packet
1926 * but we can use on a non-oplocked file. tridge proved this
1927 * on a train in Germany :-). JRA.
1928 * reply_readbraw has already checked the length.
1931 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1934 _smb_setlen(outbuf,nread);
1935 header.data = outbuf;
1939 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1940 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1941 if (errno == ENOSYS) {
1942 goto normal_readbraw;
1946 * Special hack for broken Linux with no working sendfile. If we
1947 * return EINTR we sent the header but not the rest of the data.
1948 * Fake this up by doing read/write calls.
1950 if (errno == EINTR) {
1951 /* Ensure we don't do this again. */
1952 set_use_sendfile(SNUM(conn), False);
1953 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1955 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1956 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1957 fsp->fsp_name, strerror(errno) ));
1958 exit_server("send_file_readbraw fake_sendfile failed");
1963 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1964 fsp->fsp_name, strerror(errno) ));
1965 exit_server("send_file_readbraw sendfile failed");
1975 ret = read_file(fsp,outbuf+4,startpos,nread);
1976 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1985 _smb_setlen(outbuf,ret);
1986 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1990 /****************************************************************************
1991 Reply to a readbraw (core+ protocol).
1992 ****************************************************************************/
1994 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1996 extern struct current_user current_user;
1997 ssize_t maxcount,mincount;
2000 char *header = outbuf;
2002 START_PROFILE(SMBreadbraw);
2004 if (srv_is_signing_active()) {
2005 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2009 * Special check if an oplock break has been issued
2010 * and the readraw request croses on the wire, we must
2011 * return a zero length response here.
2014 if(global_oplock_break) {
2015 _smb_setlen(header,0);
2016 if (write_data(smbd_server_fd(),header,4) != 4)
2018 DEBUG(5,("readbraw - oplock break finished\n"));
2019 END_PROFILE(SMBreadbraw);
2023 fsp = file_fsp(inbuf,smb_vwv0);
2025 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2027 * fsp could be NULL here so use the value from the packet. JRA.
2029 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2030 _smb_setlen(header,0);
2031 if (write_data(smbd_server_fd(),header,4) != 4)
2033 END_PROFILE(SMBreadbraw);
2037 CHECK_FSP(fsp,conn);
2039 flush_write_cache(fsp, READRAW_FLUSH);
2041 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2042 if(CVAL(inbuf,smb_wct) == 10) {
2044 * This is a large offset (64 bit) read.
2046 #ifdef LARGE_SMB_OFF_T
2048 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2050 #else /* !LARGE_SMB_OFF_T */
2053 * Ensure we haven't been sent a >32 bit offset.
2056 if(IVAL(inbuf,smb_vwv8) != 0) {
2057 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2058 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2059 _smb_setlen(header,0);
2060 if (write_data(smbd_server_fd(),header,4) != 4)
2062 END_PROFILE(SMBreadbraw);
2066 #endif /* LARGE_SMB_OFF_T */
2069 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2070 _smb_setlen(header,0);
2071 if (write_data(smbd_server_fd(),header,4) != 4)
2073 END_PROFILE(SMBreadbraw);
2077 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2078 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2080 /* ensure we don't overrun the packet size */
2081 maxcount = MIN(65535,maxcount);
2083 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2084 SMB_OFF_T size = fsp->size;
2085 SMB_OFF_T sizeneeded = startpos + maxcount;
2087 if (size < sizeneeded) {
2089 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
2091 if (!fsp->can_write)
2095 if (startpos >= size)
2098 nread = MIN(maxcount,(size - startpos));
2101 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2102 if (nread < mincount)
2106 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2107 (int)maxcount, (int)mincount, (int)nread ) );
2109 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2111 DEBUG(5,("readbraw finished\n"));
2112 END_PROFILE(SMBreadbraw);
2116 /****************************************************************************
2117 Reply to a lockread (core+ protocol).
2118 ****************************************************************************/
2120 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2128 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2129 BOOL my_lock_ctx = False;
2130 START_PROFILE(SMBlockread);
2132 CHECK_FSP(fsp,conn);
2135 release_level_2_oplocks_on_change(fsp);
2137 numtoread = SVAL(inbuf,smb_vwv1);
2138 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2140 outsize = set_message(outbuf,5,3,True);
2141 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2142 data = smb_buf(outbuf) + 3;
2145 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2146 * protocol request that predates the read/write lock concept.
2147 * Thus instead of asking for a read lock here we need to ask
2148 * for a write lock. JRA.
2149 * Note that the requested lock size is unaffected by max_recv.
2152 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2153 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2155 if (NT_STATUS_V(status)) {
2158 * We used to make lockread a blocking lock. It turns out
2159 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2163 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2165 * A blocking lock was requested. Package up
2166 * this smb into a queued request and push it
2167 * onto the blocking lock queue.
2169 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2170 (SMB_BIG_UINT)numtoread)) {
2171 END_PROFILE(SMBlockread);
2176 END_PROFILE(SMBlockread);
2177 return ERROR_NT(status);
2181 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2184 if (numtoread > max_recv) {
2185 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2186 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2187 (unsigned int)numtoread, (unsigned int)max_recv ));
2188 numtoread = MIN(numtoread,max_recv);
2190 nread = read_file(fsp,data,startpos,numtoread);
2193 END_PROFILE(SMBlockread);
2194 return(UNIXERROR(ERRDOS,ERRnoaccess));
2198 SSVAL(outbuf,smb_vwv0,nread);
2199 SSVAL(outbuf,smb_vwv5,nread+3);
2200 SSVAL(smb_buf(outbuf),1,nread);
2202 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2203 fsp->fnum, (int)numtoread, (int)nread));
2205 END_PROFILE(SMBlockread);
2209 /****************************************************************************
2211 ****************************************************************************/
2213 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2220 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2221 START_PROFILE(SMBread);
2223 CHECK_FSP(fsp,conn);
2226 numtoread = SVAL(inbuf,smb_vwv1);
2227 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2229 outsize = set_message(outbuf,5,3,True);
2230 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2232 * The requested read size cannot be greater than max_recv. JRA.
2234 if (numtoread > max_recv) {
2235 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2236 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2237 (unsigned int)numtoread, (unsigned int)max_recv ));
2238 numtoread = MIN(numtoread,max_recv);
2241 data = smb_buf(outbuf) + 3;
2243 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2244 END_PROFILE(SMBread);
2245 return ERROR_DOS(ERRDOS,ERRlock);
2249 nread = read_file(fsp,data,startpos,numtoread);
2252 END_PROFILE(SMBread);
2253 return(UNIXERROR(ERRDOS,ERRnoaccess));
2257 SSVAL(outbuf,smb_vwv0,nread);
2258 SSVAL(outbuf,smb_vwv5,nread+3);
2259 SCVAL(smb_buf(outbuf),0,1);
2260 SSVAL(smb_buf(outbuf),1,nread);
2262 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2263 fsp->fnum, (int)numtoread, (int)nread ) );
2265 END_PROFILE(SMBread);
2269 /****************************************************************************
2270 Reply to a read and X - possibly using sendfile.
2271 ****************************************************************************/
2273 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2274 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2278 char *data = smb_buf(outbuf);
2280 #if defined(WITH_SENDFILE)
2282 * We can only use sendfile on a non-chained packet
2283 * but we can use on a non-oplocked file. tridge proved this
2284 * on a train in Germany :-). JRA.
2287 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2288 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2289 SMB_STRUCT_STAT sbuf;
2292 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2293 return(UNIXERROR(ERRDOS,ERRnoaccess));
2295 if (startpos > sbuf.st_size)
2298 if (smb_maxcnt > (sbuf.st_size - startpos))
2299 smb_maxcnt = (sbuf.st_size - startpos);
2301 if (smb_maxcnt == 0)
2305 * Set up the packet header before send. We
2306 * assume here the sendfile will work (get the
2307 * correct amount of data).
2310 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2311 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2312 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2313 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2314 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2315 SCVAL(outbuf,smb_vwv0,0xFF);
2316 set_message(outbuf,12,smb_maxcnt,False);
2317 header.data = outbuf;
2318 header.length = data - outbuf;
2321 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2322 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2323 if (errno == ENOSYS) {
2328 * Special hack for broken Linux with no working sendfile. If we
2329 * return EINTR we sent the header but not the rest of the data.
2330 * Fake this up by doing read/write calls.
2333 if (errno == EINTR) {
2334 /* Ensure we don't do this again. */
2335 set_use_sendfile(SNUM(conn), False);
2336 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2338 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2339 len_outbuf - (data-outbuf))) == -1) {
2340 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2341 fsp->fsp_name, strerror(errno) ));
2342 exit_server("send_file_readX: fake_sendfile failed");
2344 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2345 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2346 /* Returning -1 here means successful sendfile. */
2350 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2351 fsp->fsp_name, strerror(errno) ));
2352 exit_server("send_file_readX sendfile failed");
2355 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2356 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2357 /* Returning -1 here means successful sendfile. */
2365 nread = read_file(fsp,data,startpos,smb_maxcnt);
2368 END_PROFILE(SMBreadX);
2369 return(UNIXERROR(ERRDOS,ERRnoaccess));
2372 outsize = set_message(outbuf,12,nread,False);
2373 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2374 SSVAL(outbuf,smb_vwv5,nread);
2375 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2376 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2377 SSVAL(smb_buf(outbuf),-2,nread);
2379 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2380 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2382 /* Returning the number of bytes we want to send back - including header. */
2386 /****************************************************************************
2387 Reply to a read and X.
2388 ****************************************************************************/
2390 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2392 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2393 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2395 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2397 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2400 START_PROFILE(SMBreadX);
2402 /* If it's an IPC, pass off the pipe handler. */
2404 END_PROFILE(SMBreadX);
2405 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2408 CHECK_FSP(fsp,conn);
2411 set_message(outbuf,12,0,True);
2413 if (global_client_caps & CAP_LARGE_READX) {
2414 if (SVAL(inbuf,smb_vwv7) == 1) {
2415 smb_maxcnt |= (1<<16);
2417 if (smb_maxcnt > BUFFER_SIZE) {
2418 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2419 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2420 END_PROFILE(SMBreadX);
2421 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2425 if(CVAL(inbuf,smb_wct) == 12) {
2426 #ifdef LARGE_SMB_OFF_T
2428 * This is a large offset (64 bit) read.
2430 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2432 #else /* !LARGE_SMB_OFF_T */
2435 * Ensure we haven't been sent a >32 bit offset.
2438 if(IVAL(inbuf,smb_vwv10) != 0) {
2439 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2440 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2441 END_PROFILE(SMBreadX);
2442 return ERROR_DOS(ERRDOS,ERRbadaccess);
2445 #endif /* LARGE_SMB_OFF_T */
2449 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2450 END_PROFILE(SMBreadX);
2451 return ERROR_DOS(ERRDOS,ERRlock);
2454 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2456 nread = chain_reply(inbuf,outbuf,length,bufsize);
2458 END_PROFILE(SMBreadX);
2462 /****************************************************************************
2463 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2464 ****************************************************************************/
2466 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2469 ssize_t total_written=0;
2470 size_t numtowrite=0;
2475 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2477 START_PROFILE(SMBwritebraw);
2479 if (srv_is_signing_active()) {
2480 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2483 CHECK_FSP(fsp,conn);
2486 tcount = IVAL(inbuf,smb_vwv1);
2487 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2488 write_through = BITSETW(inbuf+smb_vwv7,0);
2490 /* We have to deal with slightly different formats depending
2491 on whether we are using the core+ or lanman1.0 protocol */
2493 if(Protocol <= PROTOCOL_COREPLUS) {
2494 numtowrite = SVAL(smb_buf(inbuf),-2);
2495 data = smb_buf(inbuf);
2497 numtowrite = SVAL(inbuf,smb_vwv10);
2498 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2501 /* force the error type */
2502 SCVAL(inbuf,smb_com,SMBwritec);
2503 SCVAL(outbuf,smb_com,SMBwritec);
2505 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2506 END_PROFILE(SMBwritebraw);
2507 return(ERROR_DOS(ERRDOS,ERRlock));
2511 nwritten = write_file(fsp,data,startpos,numtowrite);
2513 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2514 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2516 if (nwritten < (ssize_t)numtowrite) {
2517 END_PROFILE(SMBwritebraw);
2518 return(UNIXERROR(ERRHRD,ERRdiskfull));
2521 total_written = nwritten;
2523 /* Return a message to the redirector to tell it to send more bytes */
2524 SCVAL(outbuf,smb_com,SMBwritebraw);
2525 SSVALS(outbuf,smb_vwv0,-1);
2526 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2527 if (!send_smb(smbd_server_fd(),outbuf))
2528 exit_server("reply_writebraw: send_smb failed.");
2530 /* Now read the raw data into the buffer and write it */
2531 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2532 exit_server("secondary writebraw failed");
2535 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2536 numtowrite = smb_len(inbuf);
2538 /* Set up outbuf to return the correct return */
2539 outsize = set_message(outbuf,1,0,True);
2540 SCVAL(outbuf,smb_com,SMBwritec);
2541 SSVAL(outbuf,smb_vwv0,total_written);
2543 if (numtowrite != 0) {
2545 if (numtowrite > BUFFER_SIZE) {
2546 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2547 (unsigned int)numtowrite ));
2548 exit_server("secondary writebraw failed");
2551 if (tcount > nwritten+numtowrite) {
2552 DEBUG(3,("Client overestimated the write %d %d %d\n",
2553 (int)tcount,(int)nwritten,(int)numtowrite));
2556 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2557 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2559 exit_server("secondary writebraw failed");
2562 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2564 if (nwritten < (ssize_t)numtowrite) {
2565 SCVAL(outbuf,smb_rcls,ERRHRD);
2566 SSVAL(outbuf,smb_err,ERRdiskfull);
2570 total_written += nwritten;
2573 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2574 sync_file(conn,fsp);
2576 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2577 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2579 /* we won't return a status if write through is not selected - this follows what WfWg does */
2580 END_PROFILE(SMBwritebraw);
2581 if (!write_through && total_written==tcount) {
2583 #if RABBIT_PELLET_FIX
2585 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2586 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2588 if (!send_keepalive(smbd_server_fd()))
2589 exit_server("reply_writebraw: send of keepalive failed");
2597 /****************************************************************************
2598 Reply to a writeunlock (core+).
2599 ****************************************************************************/
2601 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2602 int size, int dum_buffsize)
2604 ssize_t nwritten = -1;
2608 NTSTATUS status = NT_STATUS_OK;
2609 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2611 START_PROFILE(SMBwriteunlock);
2613 CHECK_FSP(fsp,conn);
2616 numtowrite = SVAL(inbuf,smb_vwv1);
2617 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2618 data = smb_buf(inbuf) + 3;
2620 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2621 END_PROFILE(SMBwriteunlock);
2622 return ERROR_DOS(ERRDOS,ERRlock);
2625 /* The special X/Open SMB protocol handling of
2626 zero length writes is *NOT* done for
2631 nwritten = write_file(fsp,data,startpos,numtowrite);
2633 if (lp_syncalways(SNUM(conn)))
2634 sync_file(conn,fsp);
2636 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2637 END_PROFILE(SMBwriteunlock);
2638 return(UNIXERROR(ERRHRD,ERRdiskfull));
2642 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2643 (SMB_BIG_UINT)startpos);
2644 if (NT_STATUS_V(status)) {
2645 END_PROFILE(SMBwriteunlock);
2646 return ERROR_NT(status);
2650 outsize = set_message(outbuf,1,0,True);
2652 SSVAL(outbuf,smb_vwv0,nwritten);
2654 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2655 fsp->fnum, (int)numtowrite, (int)nwritten));
2657 END_PROFILE(SMBwriteunlock);
2661 /****************************************************************************
2663 ****************************************************************************/
2665 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2668 ssize_t nwritten = -1;
2671 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2673 START_PROFILE(SMBwrite);
2675 /* If it's an IPC, pass off the pipe handler. */
2677 END_PROFILE(SMBwrite);
2678 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2681 CHECK_FSP(fsp,conn);
2684 numtowrite = SVAL(inbuf,smb_vwv1);
2685 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2686 data = smb_buf(inbuf) + 3;
2688 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2689 END_PROFILE(SMBwrite);
2690 return ERROR_DOS(ERRDOS,ERRlock);
2694 * X/Open SMB protocol says that if smb_vwv1 is
2695 * zero then the file size should be extended or
2696 * truncated to the size given in smb_vwv[2-3].
2699 if(numtowrite == 0) {
2701 * This is actually an allocate call, and set EOF. JRA.
2703 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2705 END_PROFILE(SMBwrite);
2706 return ERROR_NT(NT_STATUS_DISK_FULL);
2708 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2710 END_PROFILE(SMBwrite);
2711 return ERROR_NT(NT_STATUS_DISK_FULL);
2714 nwritten = write_file(fsp,data,startpos,numtowrite);
2716 if (lp_syncalways(SNUM(conn)))
2717 sync_file(conn,fsp);
2719 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2720 END_PROFILE(SMBwrite);
2721 return(UNIXERROR(ERRHRD,ERRdiskfull));
2724 outsize = set_message(outbuf,1,0,True);
2726 SSVAL(outbuf,smb_vwv0,nwritten);
2728 if (nwritten < (ssize_t)numtowrite) {
2729 SCVAL(outbuf,smb_rcls,ERRHRD);
2730 SSVAL(outbuf,smb_err,ERRdiskfull);
2733 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2735 END_PROFILE(SMBwrite);
2739 /****************************************************************************
2740 Reply to a write and X.
2741 ****************************************************************************/
2743 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2745 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2746 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2747 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2748 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2749 ssize_t nwritten = -1;
2750 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2751 unsigned int smblen = smb_len(inbuf);
2753 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2754 START_PROFILE(SMBwriteX);
2756 /* If it's an IPC, pass off the pipe handler. */
2758 END_PROFILE(SMBwriteX);
2759 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2762 CHECK_FSP(fsp,conn);
2765 /* Deal with possible LARGE_WRITEX */
2767 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2769 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2770 END_PROFILE(SMBwriteX);
2771 return ERROR_DOS(ERRDOS,ERRbadmem);
2774 data = smb_base(inbuf) + smb_doff;
2776 if(CVAL(inbuf,smb_wct) == 14) {
2777 #ifdef LARGE_SMB_OFF_T
2779 * This is a large offset (64 bit) write.
2781 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2783 #else /* !LARGE_SMB_OFF_T */
2786 * Ensure we haven't been sent a >32 bit offset.
2789 if(IVAL(inbuf,smb_vwv12) != 0) {
2790 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2791 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2792 END_PROFILE(SMBwriteX);
2793 return ERROR_DOS(ERRDOS,ERRbadaccess);
2796 #endif /* LARGE_SMB_OFF_T */
2799 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2800 END_PROFILE(SMBwriteX);
2801 return ERROR_DOS(ERRDOS,ERRlock);
2804 /* X/Open SMB protocol says that, unlike SMBwrite
2805 if the length is zero then NO truncation is
2806 done, just a write of zero. To truncate a file,
2812 nwritten = write_file(fsp,data,startpos,numtowrite);
2814 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2815 END_PROFILE(SMBwriteX);
2816 return(UNIXERROR(ERRHRD,ERRdiskfull));
2819 set_message(outbuf,6,0,True);
2821 SSVAL(outbuf,smb_vwv2,nwritten);
2823 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2825 if (nwritten < (ssize_t)numtowrite) {
2826 SCVAL(outbuf,smb_rcls,ERRHRD);
2827 SSVAL(outbuf,smb_err,ERRdiskfull);
2830 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2831 fsp->fnum, (int)numtowrite, (int)nwritten));
2833 if (lp_syncalways(SNUM(conn)) || write_through)
2834 sync_file(conn,fsp);
2836 END_PROFILE(SMBwriteX);
2837 return chain_reply(inbuf,outbuf,length,bufsize);
2840 /****************************************************************************
2842 ****************************************************************************/
2844 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2850 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2851 START_PROFILE(SMBlseek);
2853 CHECK_FSP(fsp,conn);
2855 flush_write_cache(fsp, SEEK_FLUSH);
2857 mode = SVAL(inbuf,smb_vwv1) & 3;
2858 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2859 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2868 res = fsp->pos + startpos;
2879 if (umode == SEEK_END) {
2880 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2881 if(errno == EINVAL) {
2882 SMB_OFF_T current_pos = startpos;
2883 SMB_STRUCT_STAT sbuf;
2885 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2886 END_PROFILE(SMBlseek);
2887 return(UNIXERROR(ERRDOS,ERRnoaccess));
2890 current_pos += sbuf.st_size;
2892 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2897 END_PROFILE(SMBlseek);
2898 return(UNIXERROR(ERRDOS,ERRnoaccess));
2904 outsize = set_message(outbuf,2,0,True);
2905 SIVAL(outbuf,smb_vwv0,res);
2907 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2908 fsp->fnum, (double)startpos, (double)res, mode));
2910 END_PROFILE(SMBlseek);
2914 /****************************************************************************
2916 ****************************************************************************/
2918 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2920 int outsize = set_message(outbuf,0,0,True);
2921 uint16 fnum = SVAL(inbuf,smb_vwv0);
2922 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2923 START_PROFILE(SMBflush);
2926 CHECK_FSP(fsp,conn);
2929 file_sync_all(conn);
2931 sync_file(conn,fsp);
2934 DEBUG(3,("flush\n"));
2935 END_PROFILE(SMBflush);
2939 /****************************************************************************
2941 ****************************************************************************/
2943 int reply_exit(connection_struct *conn,
2944 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2947 START_PROFILE(SMBexit);
2949 file_close_pid(SVAL(inbuf,smb_pid));
2951 outsize = set_message(outbuf,0,0,True);
2953 DEBUG(3,("exit\n"));
2955 END_PROFILE(SMBexit);
2959 /****************************************************************************
2960 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2961 ****************************************************************************/
2963 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2966 extern struct current_user current_user;
2969 int32 eclass = 0, err = 0;
2970 files_struct *fsp = NULL;
2971 START_PROFILE(SMBclose);
2973 outsize = set_message(outbuf,0,0,True);
2975 /* If it's an IPC, pass off to the pipe handler. */
2977 END_PROFILE(SMBclose);
2978 return reply_pipe_close(conn, inbuf,outbuf);
2981 fsp = file_fsp(inbuf,smb_vwv0);
2984 * We can only use CHECK_FSP if we know it's not a directory.
2987 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2988 END_PROFILE(SMBclose);
2989 return ERROR_DOS(ERRDOS,ERRbadfid);
2992 if(fsp->is_directory) {
2994 * Special case - close NT SMB directory handle.
2996 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2997 close_file(fsp,True);
3000 * Close ordinary file.
3005 /* Save the name for time set in close. */
3006 pstrcpy( file_name, fsp->fsp_name);
3008 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3010 conn->num_files_open));
3013 * Take care of any time sent in the close.
3016 mtime = make_unix_date3(inbuf+smb_vwv1);
3017 fsp_set_pending_modtime(fsp, mtime);
3020 * close_file() returns the unix errno if an error
3021 * was detected on close - normally this is due to
3022 * a disk full error. If not then it was probably an I/O error.
3025 if((close_err = close_file(fsp,True)) != 0) {
3027 END_PROFILE(SMBclose);
3028 return (UNIXERROR(ERRHRD,ERRgeneral));
3032 /* We have a cached error */
3034 END_PROFILE(SMBclose);
3035 return ERROR_DOS(eclass,err);
3038 END_PROFILE(SMBclose);
3042 /****************************************************************************
3043 Reply to a writeclose (Core+ protocol).
3044 ****************************************************************************/
3046 int reply_writeclose(connection_struct *conn,
3047 char *inbuf,char *outbuf, int size, int dum_buffsize)
3050 ssize_t nwritten = -1;
3056 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3057 START_PROFILE(SMBwriteclose);
3059 CHECK_FSP(fsp,conn);
3062 numtowrite = SVAL(inbuf,smb_vwv1);
3063 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3064 mtime = make_unix_date3(inbuf+smb_vwv4);
3065 data = smb_buf(inbuf) + 1;
3067 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3068 END_PROFILE(SMBwriteclose);
3069 return ERROR_DOS(ERRDOS,ERRlock);
3072 nwritten = write_file(fsp,data,startpos,numtowrite);
3074 set_filetime(conn, fsp->fsp_name,mtime);
3077 * More insanity. W2K only closes the file if writelen > 0.
3082 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3084 close_err = close_file(fsp,True);
3087 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3088 fsp->fnum, (int)numtowrite, (int)nwritten,
3089 conn->num_files_open));
3091 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3092 END_PROFILE(SMBwriteclose);
3093 return(UNIXERROR(ERRHRD,ERRdiskfull));
3096 if(close_err != 0) {
3098 END_PROFILE(SMBwriteclose);
3099 return(UNIXERROR(ERRHRD,ERRgeneral));
3102 outsize = set_message(outbuf,1,0,True);
3104 SSVAL(outbuf,smb_vwv0,nwritten);
3105 END_PROFILE(SMBwriteclose);
3109 /****************************************************************************
3111 ****************************************************************************/
3113 int reply_lock(connection_struct *conn,
3114 char *inbuf,char *outbuf, int length, int dum_buffsize)
3116 int outsize = set_message(outbuf,0,0,True);
3117 SMB_BIG_UINT count,offset;
3119 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3120 BOOL my_lock_ctx = False;
3122 START_PROFILE(SMBlock);
3124 CHECK_FSP(fsp,conn);
3126 release_level_2_oplocks_on_change(fsp);
3128 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3129 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3131 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3132 fsp->fd, fsp->fnum, (double)offset, (double)count));
3134 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3135 if (NT_STATUS_V(status)) {
3137 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3138 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3140 * A blocking lock was requested. Package up
3141 * this smb into a queued request and push it
3142 * onto the blocking lock queue.
3144 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3145 END_PROFILE(SMBlock);
3150 END_PROFILE(SMBlock);
3151 return ERROR_NT(status);
3154 END_PROFILE(SMBlock);
3158 /****************************************************************************
3160 ****************************************************************************/
3162 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3165 int outsize = set_message(outbuf,0,0,True);
3166 SMB_BIG_UINT count,offset;
3168 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3169 START_PROFILE(SMBunlock);
3171 CHECK_FSP(fsp,conn);
3173 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3174 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3176 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3177 if (NT_STATUS_V(status)) {
3178 END_PROFILE(SMBunlock);
3179 return ERROR_NT(status);
3182 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3183 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3185 END_PROFILE(SMBunlock);
3189 /****************************************************************************
3191 ****************************************************************************/
3193 int reply_tdis(connection_struct *conn,
3194 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3196 int outsize = set_message(outbuf,0,0,True);
3198 START_PROFILE(SMBtdis);
3200 vuid = SVAL(inbuf,smb_uid);
3203 DEBUG(4,("Invalid connection in tdis\n"));
3204 END_PROFILE(SMBtdis);
3205 return ERROR_DOS(ERRSRV,ERRinvnid);
3210 close_cnum(conn,vuid);
3212 END_PROFILE(SMBtdis);
3216 /****************************************************************************
3218 ****************************************************************************/
3220 int reply_echo(connection_struct *conn,
3221 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3223 int smb_reverb = SVAL(inbuf,smb_vwv0);
3225 unsigned int data_len = smb_buflen(inbuf);
3226 int outsize = set_message(outbuf,1,data_len,True);
3227 START_PROFILE(SMBecho);
3229 if (data_len > BUFFER_SIZE) {
3230 DEBUG(0,("reply_echo: data_len too large.\n"));
3231 END_PROFILE(SMBecho);
3235 /* copy any incoming data back out */
3237 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3239 if (smb_reverb > 100) {
3240 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3244 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3245 SSVAL(outbuf,smb_vwv0,seq_num);
3247 smb_setlen(outbuf,outsize - 4);
3249 if (!send_smb(smbd_server_fd(),outbuf))
3250 exit_server("reply_echo: send_smb failed.");
3253 DEBUG(3,("echo %d times\n", smb_reverb));
3257 END_PROFILE(SMBecho);
3261 /****************************************************************************
3262 Reply to a printopen.
3263 ****************************************************************************/
3265 int reply_printopen(connection_struct *conn,
3266 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3270 START_PROFILE(SMBsplopen);
3272 if (!CAN_PRINT(conn)) {
3273 END_PROFILE(SMBsplopen);
3274 return ERROR_DOS(ERRDOS,ERRnoaccess);
3277 /* Open for exclusive use, write only. */
3278 fsp = print_fsp_open(conn, NULL);
3281 END_PROFILE(SMBsplopen);
3282 return(UNIXERROR(ERRDOS,ERRnoaccess));
3285 outsize = set_message(outbuf,1,0,True);
3286 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3288 DEBUG(3,("openprint fd=%d fnum=%d\n",
3289 fsp->fd, fsp->fnum));
3291 END_PROFILE(SMBsplopen);
3295 /****************************************************************************
3296 Reply to a printclose.
3297 ****************************************************************************/
3299 int reply_printclose(connection_struct *conn,
3300 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3302 int outsize = set_message(outbuf,0,0,True);
3303 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3305 START_PROFILE(SMBsplclose);
3307 CHECK_FSP(fsp,conn);
3309 if (!CAN_PRINT(conn)) {
3310 END_PROFILE(SMBsplclose);
3311 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3314 DEBUG(3,("printclose fd=%d fnum=%d\n",
3315 fsp->fd,fsp->fnum));
3317 close_err = close_file(fsp,True);
3319 if(close_err != 0) {
3321 END_PROFILE(SMBsplclose);
3322 return(UNIXERROR(ERRHRD,ERRgeneral));
3325 END_PROFILE(SMBsplclose);
3329 /****************************************************************************
3330 Reply to a printqueue.
3331 ****************************************************************************/
3333 int reply_printqueue(connection_struct *conn,
3334 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3336 int outsize = set_message(outbuf,2,3,True);
3337 int max_count = SVAL(inbuf,smb_vwv0);
3338 int start_index = SVAL(inbuf,smb_vwv1);
3339 START_PROFILE(SMBsplretq);
3341 /* we used to allow the client to get the cnum wrong, but that
3342 is really quite gross and only worked when there was only
3343 one printer - I think we should now only accept it if they
3344 get it right (tridge) */
3345 if (!CAN_PRINT(conn)) {
3346 END_PROFILE(SMBsplretq);
3347 return ERROR_DOS(ERRDOS,ERRnoaccess);
3350 SSVAL(outbuf,smb_vwv0,0);
3351 SSVAL(outbuf,smb_vwv1,0);
3352 SCVAL(smb_buf(outbuf),0,1);
3353 SSVAL(smb_buf(outbuf),1,0);
3355 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3356 start_index, max_count));
3359 print_queue_struct *queue = NULL;
3360 print_status_struct status;
3361 char *p = smb_buf(outbuf) + 3;
3362 int count = print_queue_status(SNUM(conn), &queue, &status);
3363 int num_to_get = ABS(max_count);
3364 int first = (max_count>0?start_index:start_index+max_count+1);
3370 num_to_get = MIN(num_to_get,count-first);
3373 for (i=first;i<first+num_to_get;i++) {
3374 put_dos_date2(p,0,queue[i].time);
3375 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3376 SSVAL(p,5, queue[i].job);
3377 SIVAL(p,7,queue[i].size);
3379 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3384 outsize = set_message(outbuf,2,28*count+3,False);
3385 SSVAL(outbuf,smb_vwv0,count);
3386 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3387 SCVAL(smb_buf(outbuf),0,1);
3388 SSVAL(smb_buf(outbuf),1,28*count);
3393 DEBUG(3,("%d entries returned in queue\n",count));
3396 END_PROFILE(SMBsplretq);
3400 /****************************************************************************
3401 Reply to a printwrite.
3402 ****************************************************************************/
3404 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3407 int outsize = set_message(outbuf,0,0,True);
3409 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3411 START_PROFILE(SMBsplwr);
3413 if (!CAN_PRINT(conn)) {
3414 END_PROFILE(SMBsplwr);
3415 return ERROR_DOS(ERRDOS,ERRnoaccess);
3418 CHECK_FSP(fsp,conn);
3421 numtowrite = SVAL(smb_buf(inbuf),1);
3422 data = smb_buf(inbuf) + 3;
3424 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3425 END_PROFILE(SMBsplwr);
3426 return(UNIXERROR(ERRHRD,ERRdiskfull));
3429 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3431 END_PROFILE(SMBsplwr);
3435 /****************************************************************************
3436 The guts of the mkdir command, split out so it may be called by the NT SMB
3438 ****************************************************************************/
3440 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3444 if(!CAN_WRITE(conn)) {
3445 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3447 return map_nt_error_from_unix(errno);
3451 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3454 if (!check_name(directory, conn)) {
3455 if(errno == ENOENT) {
3457 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3459 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3462 return map_nt_error_from_unix(errno);
3465 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3467 if(errno == ENOENT) {
3468 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3470 return map_nt_error_from_unix(errno);
3473 return NT_STATUS_OK;
3476 /****************************************************************************
3478 ****************************************************************************/
3480 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3485 BOOL bad_path = False;
3486 SMB_STRUCT_STAT sbuf;
3488 START_PROFILE(SMBmkdir);
3490 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3491 if (!NT_STATUS_IS_OK(status)) {
3492 END_PROFILE(SMBmkdir);
3493 return ERROR_NT(status);
3496 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3498 unix_convert(directory,conn,0,&bad_path,&sbuf);
3500 if( strchr_m(directory, ':')) {
3501 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3502 END_PROFILE(SMBmkdir);
3503 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3506 status = mkdir_internal(conn, directory,bad_path);
3507 if (!NT_STATUS_IS_OK(status)) {
3508 END_PROFILE(SMBmkdir);
3509 return ERROR_NT(status);
3512 if (lp_inherit_owner(SNUM(conn))) {
3513 /* Ensure we're checking for a symlink here.... */
3514 /* We don't want to get caught by a symlink racer. */
3516 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3517 END_PROFILE(SMBmkdir);
3518 return(UNIXERROR(ERRDOS,ERRnoaccess));
3521 if(!S_ISDIR(sbuf.st_mode)) {
3522 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3523 END_PROFILE(SMBmkdir);
3524 return(UNIXERROR(ERRDOS,ERRnoaccess));
3527 change_owner_to_parent(conn, NULL, directory, &sbuf);
3530 outsize = set_message(outbuf,0,0,True);
3532 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3534 END_PROFILE(SMBmkdir);
3538 /****************************************************************************
3539 Static function used by reply_rmdir to delete an entire directory
3540 tree recursively. Return False on ok, True on fail.
3541 ****************************************************************************/
3543 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3545 const char *dname = NULL;
3548 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3553 while((dname = ReadDirName(dir_hnd, &offset))) {
3557 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3560 if (!is_visible_file(conn, directory, dname, &st, False))
3563 /* Construct the full name. */
3564 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3570 pstrcpy(fullname, directory);
3571 pstrcat(fullname, "/");
3572 pstrcat(fullname, dname);
3574 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3579 if(st.st_mode & S_IFDIR) {
3580 if(recursive_rmdir(conn, fullname)!=0) {
3584 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3588 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3597 /****************************************************************************
3598 The internals of the rmdir code - called elsewhere.
3599 ****************************************************************************/
3601 BOOL rmdir_internals(connection_struct *conn, char *directory)
3606 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3607 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3609 * Check to see if the only thing in this directory are
3610 * vetoed files/directories. If so then delete them and
3611 * retry. If we fail to delete any of them (and we *don't*
3612 * do a recursive delete) then fail the rmdir.
3614 BOOL all_veto_files = True;
3616 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3618 if(dir_hnd != NULL) {
3619 long dirpos = TellDir(dir_hnd);
3620 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3621 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3623 if (!is_visible_file(conn, directory, dname, &st, False))
3625 if(!IS_VETO_PATH(conn, dname)) {
3626 all_veto_files = False;
3631 if(all_veto_files) {
3632 SeekDir(dir_hnd,dirpos);
3633 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3636 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3638 if (!is_visible_file(conn, directory, dname, &st, False))
3641 /* Construct the full name. */
3642 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3647 pstrcpy(fullname, directory);
3648 pstrcat(fullname, "/");
3649 pstrcat(fullname, dname);
3651 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3653 if(st.st_mode & S_IFDIR) {
3654 if(lp_recursive_veto_delete(SNUM(conn))) {
3655 if(recursive_rmdir(conn, fullname) != 0)
3658 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3660 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3664 /* Retry the rmdir */
3665 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3675 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3680 /****************************************************************************
3682 ****************************************************************************/
3684 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3689 BOOL bad_path = False;
3690 SMB_STRUCT_STAT sbuf;
3692 START_PROFILE(SMBrmdir);
3694 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3695 if (!NT_STATUS_IS_OK(status)) {
3696 END_PROFILE(SMBrmdir);
3697 return ERROR_NT(status);
3700 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3702 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3704 END_PROFILE(SMBrmdir);
3705 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3708 if (check_name(directory,conn)) {
3709 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3710 ok = rmdir_internals(conn, directory);
3714 END_PROFILE(SMBrmdir);
3715 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3718 outsize = set_message(outbuf,0,0,True);
3720 DEBUG( 3, ( "rmdir %s\n", directory ) );
3722 END_PROFILE(SMBrmdir);
3726 /*******************************************************************
3727 Resolve wildcards in a filename rename.
3728 Note that name is in UNIX charset and thus potentially can be more
3729 than fstring buffer (255 bytes) especially in default UTF-8 case.
3730 Therefore, we use pstring inside and all calls should ensure that
3731 name2 is at least pstring-long (they do already)
3732 ********************************************************************/
3734 static BOOL resolve_wildcards(const char *name1, char *name2)
3736 pstring root1,root2;
3738 char *p,*p2, *pname1, *pname2;
3739 int available_space, actual_space;
3742 pname1 = strrchr_m(name1,'/');
3743 pname2 = strrchr_m(name2,'/');
3745 if (!pname1 || !pname2)
3748 pstrcpy(root1,pname1);
3749 pstrcpy(root2,pname2);
3750 p = strrchr_m(root1,'.');
3757 p = strrchr_m(root2,'.');
3771 } else if (*p2 == '*') {
3787 } else if (*p2 == '*') {
3797 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3800 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3801 if (actual_space >= available_space - 1) {
3802 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3803 actual_space - available_space));
3806 pstrcpy_base(pname2, root2, name2);
3812 /****************************************************************************
3813 Ensure open files have their names updates.
3814 ****************************************************************************/
3816 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3819 BOOL did_rename = False;
3821 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3822 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3823 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3824 fsp->fsp_name, newname ));
3825 string_set(&fsp->fsp_name, newname);
3830 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3831 (unsigned int)dev, (double)inode, newname ));
3834 /****************************************************************************
3835 Rename an open file - given an fsp.
3836 ****************************************************************************/
3838 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3840 SMB_STRUCT_STAT sbuf;
3841 BOOL bad_path = False;
3842 pstring newname_last_component;
3843 NTSTATUS error = NT_STATUS_OK;
3848 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3850 /* Quick check for "." and ".." */
3851 if (!bad_path && newname_last_component[0] == '.') {
3852 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3853 return NT_STATUS_ACCESS_DENIED;
3856 if (!rcdest && bad_path) {
3857 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3860 /* Ensure newname contains a '/' */
3861 if(strrchr_m(newname,'/') == 0) {
3864 pstrcpy(tmpstr, "./");
3865 pstrcat(tmpstr, newname);
3866 pstrcpy(newname, tmpstr);
3870 * Check for special case with case preserving and not
3871 * case sensitive. If the old last component differs from the original
3872 * last component only by case, then we should allow
3873 * the rename (user is trying to change the case of the
3877 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3878 strequal(newname, fsp->fsp_name)) {
3880 pstring newname_modified_last_component;
3883 * Get the last component of the modified name.
3884 * Note that we guarantee that newname contains a '/'
3887 p = strrchr_m(newname,'/');
3888 pstrcpy(newname_modified_last_component,p+1);
3890 if(strcsequal(newname_modified_last_component,
3891 newname_last_component) == False) {
3893 * Replace the modified last component with
3896 pstrcpy(p+1, newname_last_component);
3901 * If the src and dest names are identical - including case,
3902 * don't do the rename, just return success.
3905 if (strcsequal(fsp->fsp_name, newname)) {
3906 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3908 return NT_STATUS_OK;
3911 dest_exists = vfs_object_exist(conn,newname,NULL);
3913 if(!replace_if_exists && dest_exists) {
3914 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3915 fsp->fsp_name,newname));
3916 return NT_STATUS_OBJECT_NAME_COLLISION;
3919 error = can_rename(conn,newname,attrs,&sbuf);
3921 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3922 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3923 nt_errstr(error), fsp->fsp_name,newname));
3924 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3925 error = NT_STATUS_ACCESS_DENIED;
3929 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3930 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3931 fsp->fsp_name,newname));
3932 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3933 return NT_STATUS_OK;
3936 if (errno == ENOTDIR || errno == EISDIR)
3937 error = NT_STATUS_OBJECT_NAME_COLLISION;
3939 error = map_nt_error_from_unix(errno);
3941 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3942 nt_errstr(error), fsp->fsp_name,newname));
3947 /****************************************************************************
3948 The guts of the rename command, split out so it may be called by the NT SMB
3950 ****************************************************************************/
3952 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3956 pstring last_component_src;
3957 pstring last_component_dest;
3960 BOOL bad_path_src = False;
3961 BOOL bad_path_dest = False;
3963 NTSTATUS error = NT_STATUS_OK;
3966 SMB_STRUCT_STAT sbuf1, sbuf2;
3968 *directory = *mask = 0;
3973 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3974 if (!rc && bad_path_src) {
3975 if (ms_has_wild(last_component_src))
3976 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3977 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3980 /* Quick check for "." and ".." */
3981 if (last_component_src[0] == '.') {
3982 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3983 return NT_STATUS_OBJECT_NAME_INVALID;
3987 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3989 /* Quick check for "." and ".." */
3990 if (last_component_dest[0] == '.') {
3991 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3992 return NT_STATUS_OBJECT_NAME_INVALID;
3997 * Split the old name into directory and last component
3998 * strings. Note that unix_convert may have stripped off a
3999 * leading ./ from both name and newname if the rename is
4000 * at the root of the share. We need to make sure either both
4001 * name and newname contain a / character or neither of them do
4002 * as this is checked in resolve_wildcards().
4005 p = strrchr_m(name,'/');
4007 pstrcpy(directory,".");
4011 pstrcpy(directory,name);
4013 *p = '/'; /* Replace needed for exceptional test below. */
4017 * We should only check the mangled cache
4018 * here if unix_convert failed. This means
4019 * that the path in 'mask' doesn't exist
4020 * on the file system and so we need to look
4021 * for a possible mangle. This patch from
4022 * Tine Smukavec <valentin.smukavec@hermes.si>.
4025 if (!rc && mangle_is_mangled(mask))
4026 mangle_check_cache( mask, sizeof(pstring)-1 );
4028 has_wild = ms_has_wild(mask);
4032 * No wildcards - just process the one file.
4034 BOOL is_short_name = mangle_is_8_3(name, True);
4036 /* Add a terminating '/' to the directory name. */
4037 pstrcat(directory,"/");
4038 pstrcat(directory,mask);
4040 /* Ensure newname contains a '/' also */
4041 if(strrchr_m(newname,'/') == 0) {
4044 pstrcpy(tmpstr, "./");
4045 pstrcat(tmpstr, newname);
4046 pstrcpy(newname, tmpstr);
4049 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4050 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4051 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4052 newname, last_component_dest, is_short_name));
4055 * Check for special case with case preserving and not
4056 * case sensitive, if directory and newname are identical,
4057 * and the old last component differs from the original
4058 * last component only by case, then we should allow
4059 * the rename (user is trying to change the case of the
4062 if((conn->case_sensitive == False) &&
4063 (((conn->case_preserve == True) &&
4064 (is_short_name == False)) ||
4065 ((conn->short_case_preserve == True) &&
4066 (is_short_name == True))) &&
4067 strcsequal(directory, newname)) {
4068 pstring modified_last_component;
4071 * Get the last component of the modified name.
4072 * Note that we guarantee that newname contains a '/'
4075 p = strrchr_m(newname,'/');
4076 pstrcpy(modified_last_component,p+1);
4078 if(strcsequal(modified_last_component,
4079 last_component_dest) == False) {
4081 * Replace the modified last component with
4084 pstrcpy(p+1, last_component_dest);
4088 resolve_wildcards(directory,newname);
4091 * The source object must exist.
4094 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4095 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4096 directory,newname));
4098 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4100 * Must return different errors depending on whether the parent
4101 * directory existed or not.
4104 p = strrchr_m(directory, '/');
4106 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4108 if (vfs_object_exist(conn, directory, NULL))
4109 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4110 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4112 error = map_nt_error_from_unix(errno);
4113 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4114 nt_errstr(error), directory,newname));
4119 if (!rcdest && bad_path_dest) {
4120 if (ms_has_wild(last_component_dest))
4121 return NT_STATUS_OBJECT_NAME_INVALID;
4122 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4125 error = can_rename(conn,directory,attrs,&sbuf1);
4127 if (!NT_STATUS_IS_OK(error)) {
4128 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4129 nt_errstr(error), directory,newname));
4134 * If the src and dest names are identical - including case,
4135 * don't do the rename, just return success.
4138 if (strcsequal(directory, newname)) {
4139 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4140 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4141 return NT_STATUS_OK;
4144 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4145 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4146 directory,newname));
4147 return NT_STATUS_OBJECT_NAME_COLLISION;
4150 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4151 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4152 directory,newname));
4153 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4154 return NT_STATUS_OK;
4157 if (errno == ENOTDIR || errno == EISDIR)
4158 error = NT_STATUS_OBJECT_NAME_COLLISION;
4160 error = map_nt_error_from_unix(errno);
4162 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4163 nt_errstr(error), directory,newname));
4168 * Wildcards - process each file that matches.
4170 struct smb_Dir *dir_hnd = NULL;
4174 if (check_name(directory,conn))
4175 dir_hnd = OpenDir(conn, directory);
4179 error = NT_STATUS_NO_SUCH_FILE;
4180 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4182 if (strequal(mask,"????????.???"))
4185 while ((dname = ReadDirName(dir_hnd, &offset))) {
4187 BOOL sysdir_entry = False;
4189 pstrcpy(fname,dname);
4191 /* Quick check for "." and ".." */
4192 if (fname[0] == '.') {
4193 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4195 sysdir_entry = True;
4202 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4205 if(!mask_match(fname, mask, conn->case_sensitive))
4209 error = NT_STATUS_OBJECT_NAME_INVALID;
4213 error = NT_STATUS_ACCESS_DENIED;
4214 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4215 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4216 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4217 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4220 error = can_rename(conn,fname,attrs,&sbuf1);
4221 if (!NT_STATUS_IS_OK(error)) {
4222 DEBUG(6,("rename %s refused\n", fname));
4225 pstrcpy(destname,newname);
4227 if (!resolve_wildcards(fname,destname)) {
4228 DEBUG(6,("resolve_wildcards %s %s failed\n",
4233 if (strcsequal(fname,destname)) {
4234 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4235 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4237 error = NT_STATUS_OK;
4241 if (!replace_if_exists &&
4242 vfs_file_exist(conn,destname, NULL)) {
4243 DEBUG(6,("file_exist %s\n", destname));
4244 error = NT_STATUS_OBJECT_NAME_COLLISION;
4248 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4249 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4251 error = NT_STATUS_OK;
4253 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4258 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4259 if (!rcdest && bad_path_dest) {
4260 if (ms_has_wild(last_component_dest))
4261 return NT_STATUS_OBJECT_NAME_INVALID;
4262 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4267 if (count == 0 && NT_STATUS_IS_OK(error)) {
4268 error = map_nt_error_from_unix(errno);
4274 /****************************************************************************
4276 ****************************************************************************/
4278 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4285 uint16 attrs = SVAL(inbuf,smb_vwv0);
4288 START_PROFILE(SMBmv);
4290 p = smb_buf(inbuf) + 1;
4291 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4292 if (!NT_STATUS_IS_OK(status)) {
4294 return ERROR_NT(status);
4297 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4298 if (!NT_STATUS_IS_OK(status)) {
4300 return ERROR_NT(status);
4303 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4304 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4306 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4308 status = rename_internals(conn, name, newname, attrs, False);
4309 if (!NT_STATUS_IS_OK(status)) {
4311 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4312 /* We have re-scheduled this call. */
4315 return ERROR_NT(status);
4319 * Win2k needs a changenotify request response before it will
4320 * update after a rename..
4322 process_pending_change_notify_queue((time_t)0);
4323 outsize = set_message(outbuf,0,0,True);
4329 /*******************************************************************
4330 Copy a file as part of a reply_copy.
4331 ******************************************************************/
4333 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4334 int count,BOOL target_is_directory, int *err_ret)
4337 SMB_STRUCT_STAT src_sbuf, sbuf2;
4339 files_struct *fsp1,*fsp2;
4345 pstrcpy(dest,dest1);
4346 if (target_is_directory) {
4347 char *p = strrchr_m(src,'/');
4356 if (!vfs_file_exist(conn,src,&src_sbuf))
4359 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4360 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4366 if (!target_is_directory && count)
4367 ofun = FILE_EXISTS_OPEN;
4369 dosattrs = dos_mode(conn, src, &src_sbuf);
4370 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4371 ZERO_STRUCTP(&sbuf2);
4373 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4374 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4377 close_file(fsp1,False);
4381 if ((ofun&3) == 1) {
4382 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4383 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4385 * Stop the copy from occurring.
4388 src_sbuf.st_size = 0;
4392 if (src_sbuf.st_size)
4393 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4395 close_file(fsp1,False);
4397 /* Ensure the modtime is set correctly on the destination file. */
4398 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4401 * As we are opening fsp1 read-only we only expect
4402 * an error on close on fsp2 if we are out of space.
4403 * Thus we don't look at the error return from the
4406 *err_ret = close_file(fsp2,False);
4408 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4411 /****************************************************************************
4412 Reply to a file copy.
4413 ****************************************************************************/
4415 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4420 pstring mask,newname;
4423 int error = ERRnoaccess;
4427 int tid2 = SVAL(inbuf,smb_vwv0);
4428 int ofun = SVAL(inbuf,smb_vwv1);
4429 int flags = SVAL(inbuf,smb_vwv2);
4430 BOOL target_is_directory=False;
4431 BOOL bad_path1 = False;
4432 BOOL bad_path2 = False;
4434 SMB_STRUCT_STAT sbuf1, sbuf2;
4437 START_PROFILE(SMBcopy);
4439 *directory = *mask = 0;
4442 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 END_PROFILE(SMBcopy);
4445 return ERROR_NT(status);
4447 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4448 if (!NT_STATUS_IS_OK(status)) {
4449 END_PROFILE(SMBcopy);
4450 return ERROR_NT(status);
4453 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4455 if (tid2 != conn->cnum) {
4456 /* can't currently handle inter share copies XXXX */
4457 DEBUG(3,("Rejecting inter-share copy\n"));
4458 END_PROFILE(SMBcopy);
4459 return ERROR_DOS(ERRSRV,ERRinvdevice);
4462 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4463 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4465 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4466 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4468 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4470 if ((flags&1) && target_is_directory) {
4471 END_PROFILE(SMBcopy);
4472 return ERROR_DOS(ERRDOS,ERRbadfile);
4475 if ((flags&2) && !target_is_directory) {
4476 END_PROFILE(SMBcopy);
4477 return ERROR_DOS(ERRDOS,ERRbadpath);
4480 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4481 /* wants a tree copy! XXXX */
4482 DEBUG(3,("Rejecting tree copy\n"));
4483 END_PROFILE(SMBcopy);
4484 return ERROR_DOS(ERRSRV,ERRerror);
4487 p = strrchr_m(name,'/');
4489 pstrcpy(directory,"./");
4493 pstrcpy(directory,name);
4498 * We should only check the mangled cache
4499 * here if unix_convert failed. This means
4500 * that the path in 'mask' doesn't exist
4501 * on the file system and so we need to look
4502 * for a possible mangle. This patch from
4503 * Tine Smukavec <valentin.smukavec@hermes.si>.
4506 if (!rc && mangle_is_mangled(mask))
4507 mangle_check_cache( mask, sizeof(pstring)-1 );
4509 has_wild = ms_has_wild(mask);
4512 pstrcat(directory,"/");
4513 pstrcat(directory,mask);
4514 if (resolve_wildcards(directory,newname) &&
4515 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4519 END_PROFILE(SMBcopy);
4520 return(UNIXERROR(ERRHRD,ERRgeneral));
4523 exists = vfs_file_exist(conn,directory,NULL);
4526 struct smb_Dir *dir_hnd = NULL;
4530 if (check_name(directory,conn))
4531 dir_hnd = OpenDir(conn, directory);
4537 if (strequal(mask,"????????.???"))
4540 while ((dname = ReadDirName(dir_hnd, &offset))) {
4542 pstrcpy(fname,dname);
4544 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4547 if(!mask_match(fname, mask, conn->case_sensitive))
4550 error = ERRnoaccess;
4551 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4552 pstrcpy(destname,newname);
4553 if (resolve_wildcards(fname,destname) &&
4554 copy_file(fname,destname,conn,ofun,
4555 count,target_is_directory,&err))
4557 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4565 /* Error on close... */
4567 END_PROFILE(SMBcopy);
4568 return(UNIXERROR(ERRHRD,ERRgeneral));
4572 END_PROFILE(SMBcopy);
4573 return ERROR_DOS(ERRDOS,error);
4575 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4576 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4578 END_PROFILE(SMBcopy);
4579 return(UNIXERROR(ERRDOS,error));
4583 outsize = set_message(outbuf,1,0,True);
4584 SSVAL(outbuf,smb_vwv0,count);
4586 END_PROFILE(SMBcopy);
4590 /****************************************************************************
4592 ****************************************************************************/
4594 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4602 START_PROFILE(pathworks_setdir);
4605 if (!CAN_SETDIR(snum)) {
4606 END_PROFILE(pathworks_setdir);
4607 return ERROR_DOS(ERRDOS,ERRnoaccess);
4610 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4611 if (!NT_STATUS_IS_OK(status)) {
4612 END_PROFILE(pathworks_setdir);
4613 return ERROR_NT(status);
4616 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4618 if (strlen(newdir) == 0) {
4621 ok = vfs_directory_exist(conn,newdir,NULL);
4623 string_set(&conn->connectpath,newdir);
4627 END_PROFILE(pathworks_setdir);
4628 return ERROR_DOS(ERRDOS,ERRbadpath);
4631 outsize = set_message(outbuf,0,0,True);
4632 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4634 DEBUG(3,("setdir %s\n", newdir));
4636 END_PROFILE(pathworks_setdir);
4640 /****************************************************************************
4641 Get a lock pid, dealing with large count requests.
4642 ****************************************************************************/
4644 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4646 if(!large_file_format)
4647 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4649 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4652 /****************************************************************************
4653 Get a lock count, dealing with large count requests.
4654 ****************************************************************************/
4656 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4658 SMB_BIG_UINT count = 0;
4660 if(!large_file_format) {
4661 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4664 #if defined(HAVE_LONGLONG)
4665 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4666 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4667 #else /* HAVE_LONGLONG */
4670 * NT4.x seems to be broken in that it sends large file (64 bit)
4671 * lockingX calls even if the CAP_LARGE_FILES was *not*
4672 * negotiated. For boxes without large unsigned ints truncate the
4673 * lock count by dropping the top 32 bits.
4676 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4677 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4678 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4679 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4680 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4683 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4684 #endif /* HAVE_LONGLONG */
4690 #if !defined(HAVE_LONGLONG)
4691 /****************************************************************************
4692 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4693 ****************************************************************************/
4695 static uint32 map_lock_offset(uint32 high, uint32 low)
4699 uint32 highcopy = high;
4702 * Try and find out how many significant bits there are in high.
4705 for(i = 0; highcopy; i++)
4709 * We use 31 bits not 32 here as POSIX
4710 * lock offsets may not be negative.
4713 mask = (~0) << (31 - i);
4716 return 0; /* Fail. */
4722 #endif /* !defined(HAVE_LONGLONG) */
4724 /****************************************************************************
4725 Get a lock offset, dealing with large offset requests.
4726 ****************************************************************************/
4728 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4730 SMB_BIG_UINT offset = 0;
4734 if(!large_file_format) {
4735 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4738 #if defined(HAVE_LONGLONG)
4739 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4740 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4741 #else /* HAVE_LONGLONG */
4744 * NT4.x seems to be broken in that it sends large file (64 bit)
4745 * lockingX calls even if the CAP_LARGE_FILES was *not*
4746 * negotiated. For boxes without large unsigned ints mangle the
4747 * lock offset by mapping the top 32 bits onto the lower 32.
4750 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4751 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4752 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4755 if((new_low = map_lock_offset(high, low)) == 0) {
4757 return (SMB_BIG_UINT)-1;
4760 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4761 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4762 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4763 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4766 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4767 #endif /* HAVE_LONGLONG */
4773 /****************************************************************************
4774 Reply to a lockingX request.
4775 ****************************************************************************/
4777 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4779 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4780 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4781 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4782 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4783 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4784 SMB_BIG_UINT count = 0, offset = 0;
4786 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4789 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4791 BOOL my_lock_ctx = False;
4794 START_PROFILE(SMBlockingX);
4796 CHECK_FSP(fsp,conn);
4798 data = smb_buf(inbuf);
4800 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4801 /* we don't support these - and CANCEL_LOCK makes w2k
4802 and XP reboot so I don't really want to be
4803 compatible! (tridge) */
4804 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4807 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4808 /* Need to make this like a cancel.... JRA. */
4809 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4812 /* Check if this is an oplock break on a file
4813 we have granted an oplock on.
4815 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4816 /* Client can insist on breaking to none. */
4817 BOOL break_to_none = (oplocklevel == 0);
4819 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4820 (unsigned int)oplocklevel, fsp->fnum ));
4823 * Make sure we have granted an exclusive or batch oplock on this file.
4826 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4827 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4828 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4830 /* if this is a pure oplock break request then don't send a reply */
4831 if (num_locks == 0 && num_ulocks == 0) {
4832 END_PROFILE(SMBlockingX);
4835 END_PROFILE(SMBlockingX);
4836 return ERROR_DOS(ERRDOS,ERRlock);
4840 if (remove_oplock(fsp, break_to_none) == False) {
4841 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4845 /* if this is a pure oplock break request then don't send a reply */
4846 if (num_locks == 0 && num_ulocks == 0) {
4847 /* Sanity check - ensure a pure oplock break is not a
4849 if(CVAL(inbuf,smb_vwv0) != 0xff)
4850 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4851 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4852 END_PROFILE(SMBlockingX);
4858 * We do this check *after* we have checked this is not a oplock break
4859 * response message. JRA.
4862 release_level_2_oplocks_on_change(fsp);
4864 /* Data now points at the beginning of the list
4865 of smb_unlkrng structs */
4866 for(i = 0; i < (int)num_ulocks; i++) {
4867 lock_pid = get_lock_pid( data, i, large_file_format);
4868 count = get_lock_count( data, i, large_file_format);
4869 offset = get_lock_offset( data, i, large_file_format, &err);
4872 * There is no error code marked "stupid client bug".... :-).
4875 END_PROFILE(SMBlockingX);
4876 return ERROR_DOS(ERRDOS,ERRnoaccess);
4879 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4880 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4882 status = do_unlock(fsp,conn,lock_pid,count,offset);
4883 if (NT_STATUS_V(status)) {
4884 END_PROFILE(SMBlockingX);
4885 return ERROR_NT(status);
4889 /* Setup the timeout in seconds. */
4891 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4893 /* Now do any requested locks */
4894 data += ((large_file_format ? 20 : 10)*num_ulocks);
4896 /* Data now points at the beginning of the list
4897 of smb_lkrng structs */
4899 for(i = 0; i < (int)num_locks; i++) {
4900 lock_pid = get_lock_pid( data, i, large_file_format);
4901 count = get_lock_count( data, i, large_file_format);
4902 offset = get_lock_offset( data, i, large_file_format, &err);
4905 * There is no error code marked "stupid client bug".... :-).
4908 END_PROFILE(SMBlockingX);
4909 return ERROR_DOS(ERRDOS,ERRnoaccess);
4912 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4913 (double)offset, (double)count, (unsigned int)lock_pid,
4914 fsp->fsp_name, (int)lock_timeout ));
4916 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4917 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4918 if (NT_STATUS_V(status)) {
4920 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4921 * Even if it's our own lock context, we need to wait here as
4922 * there may be an unlock on the way.
4923 * So I removed a "&& !my_lock_ctx" from the following
4924 * if statement. JRA.
4926 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4928 * A blocking lock was requested. Package up
4929 * this smb into a queued request and push it
4930 * onto the blocking lock queue.
4932 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4933 END_PROFILE(SMBlockingX);
4941 /* If any of the above locks failed, then we must unlock
4942 all of the previous locks (X/Open spec). */
4943 if (i != num_locks && num_locks != 0) {
4945 * Ensure we don't do a remove on the lock that just failed,
4946 * as under POSIX rules, if we have a lock already there, we
4947 * will delete it (and we shouldn't) .....
4949 for(i--; i >= 0; i--) {
4950 lock_pid = get_lock_pid( data, i, large_file_format);
4951 count = get_lock_count( data, i, large_file_format);
4952 offset = get_lock_offset( data, i, large_file_format, &err);
4955 * There is no error code marked "stupid client bug".... :-).
4958 END_PROFILE(SMBlockingX);
4959 return ERROR_DOS(ERRDOS,ERRnoaccess);
4962 do_unlock(fsp,conn,lock_pid,count,offset);
4964 END_PROFILE(SMBlockingX);
4965 return ERROR_NT(status);
4968 set_message(outbuf,2,0,True);
4970 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4971 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4973 END_PROFILE(SMBlockingX);
4974 return chain_reply(inbuf,outbuf,length,bufsize);
4977 /****************************************************************************
4978 Reply to a SMBreadbmpx (read block multiplex) request.
4979 ****************************************************************************/
4981 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4992 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4993 START_PROFILE(SMBreadBmpx);
4995 /* this function doesn't seem to work - disable by default */
4996 if (!lp_readbmpx()) {
4997 END_PROFILE(SMBreadBmpx);
4998 return ERROR_DOS(ERRSRV,ERRuseSTD);
5001 outsize = set_message(outbuf,8,0,True);
5003 CHECK_FSP(fsp,conn);
5006 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5007 maxcount = SVAL(inbuf,smb_vwv3);
5009 data = smb_buf(outbuf);
5010 pad = ((long)data)%4;
5015 max_per_packet = bufsize-(outsize+pad);
5019 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5020 END_PROFILE(SMBreadBmpx);
5021 return ERROR_DOS(ERRDOS,ERRlock);
5025 size_t N = MIN(max_per_packet,tcount-total_read);
5027 nread = read_file(fsp,data,startpos,N);
5032 if (nread < (ssize_t)N)
5033 tcount = total_read + nread;
5035 set_message(outbuf,8,nread,False);
5036 SIVAL(outbuf,smb_vwv0,startpos);
5037 SSVAL(outbuf,smb_vwv2,tcount);
5038 SSVAL(outbuf,smb_vwv6,nread);
5039 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5041 if (!send_smb(smbd_server_fd(),outbuf))
5042 exit_server("reply_readbmpx: send_smb failed.");
5044 total_read += nread;
5046 } while (total_read < (ssize_t)tcount);
5048 END_PROFILE(SMBreadBmpx);
5052 /****************************************************************************
5053 Reply to a SMBsetattrE.
5054 ****************************************************************************/
5056 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5058 struct utimbuf unix_times;
5060 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5061 START_PROFILE(SMBsetattrE);
5063 outsize = set_message(outbuf,0,0,True);
5065 if(!fsp || (fsp->conn != conn)) {
5066 END_PROFILE(SMBgetattrE);
5067 return ERROR_DOS(ERRDOS,ERRbadfid);
5071 * Convert the DOS times into unix times. Ignore create
5072 * time as UNIX can't set this.
5075 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5076 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5079 * Patch from Ray Frush <frush@engr.colostate.edu>
5080 * Sometimes times are sent as zero - ignore them.
5083 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5084 /* Ignore request */
5085 if( DEBUGLVL( 3 ) ) {
5086 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5087 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5089 END_PROFILE(SMBsetattrE);
5091 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5092 /* set modify time = to access time if modify time was unset */
5093 unix_times.modtime = unix_times.actime;
5096 /* Set the date on this file */
5097 /* Should we set pending modtime here ? JRA */
5098 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5099 END_PROFILE(SMBsetattrE);
5100 return ERROR_DOS(ERRDOS,ERRnoaccess);
5103 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5104 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5106 END_PROFILE(SMBsetattrE);
5111 /* Back from the dead for OS/2..... JRA. */
5113 /****************************************************************************
5114 Reply to a SMBwritebmpx (write block multiplex primary) request.
5115 ****************************************************************************/
5117 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5120 ssize_t nwritten = -1;
5127 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5128 START_PROFILE(SMBwriteBmpx);
5130 CHECK_FSP(fsp,conn);
5132 if (HAS_CACHED_ERROR(fsp)) {
5133 return(CACHED_ERROR(fsp));
5136 tcount = SVAL(inbuf,smb_vwv1);
5137 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5138 write_through = BITSETW(inbuf+smb_vwv7,0);
5139 numtowrite = SVAL(inbuf,smb_vwv10);
5140 smb_doff = SVAL(inbuf,smb_vwv11);
5142 data = smb_base(inbuf) + smb_doff;
5144 /* If this fails we need to send an SMBwriteC response,
5145 not an SMBwritebmpx - set this up now so we don't forget */
5146 SCVAL(outbuf,smb_com,SMBwritec);
5148 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5149 END_PROFILE(SMBwriteBmpx);
5150 return(ERROR_DOS(ERRDOS,ERRlock));
5153 nwritten = write_file(fsp,data,startpos,numtowrite);
5155 if(lp_syncalways(SNUM(conn)) || write_through)
5156 sync_file(conn,fsp);
5158 if(nwritten < (ssize_t)numtowrite) {
5159 END_PROFILE(SMBwriteBmpx);
5160 return(UNIXERROR(ERRHRD,ERRdiskfull));
5163 /* If the maximum to be written to this file
5164 is greater than what we just wrote then set
5165 up a secondary struct to be attached to this
5166 fd, we will use this to cache error messages etc. */
5168 if((ssize_t)tcount > nwritten) {
5169 write_bmpx_struct *wbms;
5170 if(fsp->wbmpx_ptr != NULL)
5171 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5173 wbms = SMB_MALLOC_P(write_bmpx_struct);
5175 DEBUG(0,("Out of memory in reply_readmpx\n"));
5176 END_PROFILE(SMBwriteBmpx);
5177 return(ERROR_DOS(ERRSRV,ERRnoresource));
5179 wbms->wr_mode = write_through;
5180 wbms->wr_discard = False; /* No errors yet */
5181 wbms->wr_total_written = nwritten;
5182 wbms->wr_errclass = 0;
5184 fsp->wbmpx_ptr = wbms;
5187 /* We are returning successfully, set the message type back to
5189 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5191 outsize = set_message(outbuf,1,0,True);
5193 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5195 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5196 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5198 if (write_through && tcount==nwritten) {
5199 /* We need to send both a primary and a secondary response */
5200 smb_setlen(outbuf,outsize - 4);
5201 if (!send_smb(smbd_server_fd(),outbuf))
5202 exit_server("reply_writebmpx: send_smb failed.");
5204 /* Now the secondary */
5205 outsize = set_message(outbuf,1,0,True);
5206 SCVAL(outbuf,smb_com,SMBwritec);
5207 SSVAL(outbuf,smb_vwv0,nwritten);
5210 END_PROFILE(SMBwriteBmpx);
5214 /****************************************************************************
5215 Reply to a SMBwritebs (write block multiplex secondary) request.
5216 ****************************************************************************/
5218 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5221 ssize_t nwritten = -1;
5228 write_bmpx_struct *wbms;
5229 BOOL send_response = False;
5230 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5231 START_PROFILE(SMBwriteBs);
5233 CHECK_FSP(fsp,conn);
5236 tcount = SVAL(inbuf,smb_vwv1);
5237 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5238 numtowrite = SVAL(inbuf,smb_vwv6);
5239 smb_doff = SVAL(inbuf,smb_vwv7);
5241 data = smb_base(inbuf) + smb_doff;
5243 /* We need to send an SMBwriteC response, not an SMBwritebs */
5244 SCVAL(outbuf,smb_com,SMBwritec);
5246 /* This fd should have an auxiliary struct attached,
5247 check that it does */
5248 wbms = fsp->wbmpx_ptr;
5250 END_PROFILE(SMBwriteBs);
5254 /* If write through is set we can return errors, else we must cache them */
5255 write_through = wbms->wr_mode;
5257 /* Check for an earlier error */
5258 if(wbms->wr_discard) {
5259 END_PROFILE(SMBwriteBs);
5260 return -1; /* Just discard the packet */
5263 nwritten = write_file(fsp,data,startpos,numtowrite);
5265 if(lp_syncalways(SNUM(conn)) || write_through)
5266 sync_file(conn,fsp);
5268 if (nwritten < (ssize_t)numtowrite) {
5270 /* We are returning an error - we can delete the aux struct */
5273 fsp->wbmpx_ptr = NULL;
5274 END_PROFILE(SMBwriteBs);
5275 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5277 wbms->wr_errclass = ERRHRD;
5278 wbms->wr_error = ERRdiskfull;
5279 wbms->wr_status = NT_STATUS_DISK_FULL;
5280 wbms->wr_discard = True;
5281 END_PROFILE(SMBwriteBs);
5285 /* Increment the total written, if this matches tcount
5286 we can discard the auxiliary struct (hurrah !) and return a writeC */
5287 wbms->wr_total_written += nwritten;
5288 if(wbms->wr_total_written >= tcount) {
5289 if (write_through) {
5290 outsize = set_message(outbuf,1,0,True);
5291 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5292 send_response = True;
5296 fsp->wbmpx_ptr = NULL;
5300 END_PROFILE(SMBwriteBs);
5304 END_PROFILE(SMBwriteBs);
5308 /****************************************************************************
5309 Reply to a SMBgetattrE.
5310 ****************************************************************************/
5312 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5314 SMB_STRUCT_STAT sbuf;
5317 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5318 START_PROFILE(SMBgetattrE);
5320 outsize = set_message(outbuf,11,0,True);
5322 if(!fsp || (fsp->conn != conn)) {
5323 END_PROFILE(SMBgetattrE);
5324 return ERROR_DOS(ERRDOS,ERRbadfid);
5327 /* Do an fstat on this file */
5328 if(fsp_stat(fsp, &sbuf)) {
5329 END_PROFILE(SMBgetattrE);
5330 return(UNIXERROR(ERRDOS,ERRnoaccess));
5333 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5336 * Convert the times into dos times. Set create
5337 * date to be last modify date as UNIX doesn't save
5341 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5342 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5343 /* Should we check pending modtime here ? JRA */
5344 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5347 SIVAL(outbuf,smb_vwv6,0);
5348 SIVAL(outbuf,smb_vwv8,0);
5350 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5351 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5352 SIVAL(outbuf,smb_vwv8,allocation_size);
5354 SSVAL(outbuf,smb_vwv10, mode);
5356 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5358 END_PROFILE(SMBgetattrE);