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 START_PROFILE(SMBsearch);
936 *mask = *directory = *fname = 0;
938 /* If we were called as SMBffirst then we must expect close. */
939 if(CVAL(inbuf,smb_com) == SMBffirst)
942 outsize = set_message(outbuf,1,3,True);
943 maxentries = SVAL(inbuf,smb_vwv0);
944 dirtype = SVAL(inbuf,smb_vwv1);
945 p = smb_buf(inbuf) + 1;
946 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
947 if (!NT_STATUS_IS_OK(nt_status)) {
948 END_PROFILE(SMBsearch);
949 return ERROR_NT(nt_status);
952 RESOLVE_DFSPATH(path, conn, inbuf, outbuf);
955 status_len = SVAL(p, 0);
958 /* dirtype &= ~aDIR; */
960 if (status_len == 0) {
961 SMB_STRUCT_STAT sbuf;
964 pstrcpy(directory,path);
966 unix_convert(directory,conn,0,&bad_path,&sbuf);
969 if (!check_name(directory,conn))
972 p = strrchr_m(dir2,'/');
981 p = strrchr_m(directory,'/');
987 if (strlen(directory) == 0)
988 pstrcpy(directory,".");
989 memset((char *)status,'\0',21);
990 SCVAL(status,0,(dirtype & 0x1F));
995 status_dirtype = CVAL(status,0) & 0x1F;
996 if (status_dirtype != (dirtype & 0x1F))
997 dirtype = status_dirtype;
999 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1002 string_set(&conn->dirpath,dptr_path(dptr_num));
1003 pstrcpy(mask, dptr_wcard(dptr_num));
1007 p = smb_buf(outbuf) + 3;
1010 if (status_len == 0) {
1011 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1013 if(dptr_num == -2) {
1014 END_PROFILE(SMBsearch);
1015 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1017 END_PROFILE(SMBsearch);
1018 return ERROR_DOS(ERRDOS,ERRnofids);
1020 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1021 END_PROFILE(SMBsearch);
1022 return ERROR_DOS(ERRDOS,ERRnomem);
1025 dirtype = dptr_attr(dptr_num);
1028 DEBUG(4,("dptr_num is %d\n",dptr_num));
1031 if ((dirtype&0x1F) == aVOLID) {
1032 memcpy(p,status,21);
1033 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1034 dptr_fill(p+12,dptr_num);
1035 if (dptr_zero(p+12) && (status_len==0))
1039 p += DIR_STRUCT_SIZE;
1042 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1044 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1045 conn->dirpath,lp_dontdescend(SNUM(conn))));
1046 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1047 check_descend = True;
1049 for (i=numentries;(i<maxentries) && !finished;i++) {
1050 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1052 memcpy(p,status,21);
1053 make_dir_struct(p,mask,fname,size,mode,date);
1054 dptr_fill(p+12,dptr_num);
1056 p += DIR_STRUCT_SIZE;
1066 /* If we were called as SMBffirst with smb_search_id == NULL
1067 and no entries were found then return error and close dirptr
1070 if (numentries == 0 || !ok) {
1071 dptr_close(&dptr_num);
1072 } else if(ok && expect_close && status_len == 0) {
1073 /* Close the dptr - we know it's gone */
1074 dptr_close(&dptr_num);
1077 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1078 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1079 dptr_close(&dptr_num);
1082 if ((numentries == 0) && !ms_has_wild(mask)) {
1083 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1086 SSVAL(outbuf,smb_vwv0,numentries);
1087 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1088 SCVAL(smb_buf(outbuf),0,5);
1089 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1091 if (Protocol >= PROTOCOL_NT1)
1092 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1094 outsize += DIR_STRUCT_SIZE*numentries;
1095 smb_setlen(outbuf,outsize - 4);
1097 if ((! *directory) && dptr_path(dptr_num))
1098 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1100 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1101 smb_fn_name(CVAL(inbuf,smb_com)),
1102 mask, directory, dirtype, numentries, maxentries ) );
1104 END_PROFILE(SMBsearch);
1108 /****************************************************************************
1109 Reply to a fclose (stop directory search).
1110 ****************************************************************************/
1112 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1122 START_PROFILE(SMBfclose);
1124 outsize = set_message(outbuf,1,0,True);
1125 p = smb_buf(inbuf) + 1;
1126 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1127 if (!NT_STATUS_IS_OK(err)) {
1128 END_PROFILE(SMBfclose);
1129 return ERROR_NT(err);
1132 status_len = SVAL(p,0);
1135 if (status_len == 0) {
1136 END_PROFILE(SMBfclose);
1137 return ERROR_DOS(ERRSRV,ERRsrverror);
1140 memcpy(status,p,21);
1142 if(dptr_fetch(status+12,&dptr_num)) {
1143 /* Close the dptr - we know it's gone */
1144 dptr_close(&dptr_num);
1147 SSVAL(outbuf,smb_vwv0,0);
1149 DEBUG(3,("search close\n"));
1151 END_PROFILE(SMBfclose);
1155 /****************************************************************************
1157 ****************************************************************************/
1159 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1168 SMB_STRUCT_STAT sbuf;
1169 BOOL bad_path = False;
1171 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1172 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1174 START_PROFILE(SMBopen);
1176 share_mode = SVAL(inbuf,smb_vwv0);
1178 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 END_PROFILE(SMBopen);
1181 return ERROR_NT(status);
1184 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1186 unix_convert(fname,conn,0,&bad_path,&sbuf);
1188 END_PROFILE(SMBopen);
1189 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1192 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1193 (uint32)dos_attr, oplock_request,&rmode,NULL);
1196 END_PROFILE(SMBopen);
1197 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1198 /* We have re-scheduled this call. */
1199 clear_cached_errors();
1202 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1205 size = sbuf.st_size;
1206 fmode = dos_mode(conn,fname,&sbuf);
1207 mtime = sbuf.st_mtime;
1210 DEBUG(3,("attempt to open a directory %s\n",fname));
1211 close_file(fsp,False);
1212 END_PROFILE(SMBopen);
1213 return ERROR_DOS(ERRDOS,ERRnoaccess);
1216 outsize = set_message(outbuf,7,0,True);
1217 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1218 SSVAL(outbuf,smb_vwv1,fmode);
1219 if(lp_dos_filetime_resolution(SNUM(conn)) )
1220 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1222 put_dos_date3(outbuf,smb_vwv2,mtime);
1223 SIVAL(outbuf,smb_vwv4,(uint32)size);
1224 SSVAL(outbuf,smb_vwv6,rmode);
1226 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1227 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1229 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1230 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1231 END_PROFILE(SMBopen);
1235 /****************************************************************************
1236 Reply to an open and X.
1237 ****************************************************************************/
1239 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1242 int smb_mode = SVAL(inbuf,smb_vwv3);
1243 int smb_attr = SVAL(inbuf,smb_vwv5);
1244 /* Breakout the oplock request bits so we can set the
1245 reply bits separately. */
1246 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1247 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1248 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1250 int open_flags = SVAL(inbuf,smb_vwv2);
1251 int smb_sattr = SVAL(inbuf,smb_vwv4);
1252 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1254 int smb_ofun = SVAL(inbuf,smb_vwv8);
1256 int fmode=0,mtime=0,rmode=0;
1257 SMB_STRUCT_STAT sbuf;
1259 BOOL bad_path = False;
1262 START_PROFILE(SMBopenX);
1264 /* If it's an IPC, pass off the pipe handler. */
1266 if (lp_nt_pipe_support()) {
1267 END_PROFILE(SMBopenX);
1268 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1270 END_PROFILE(SMBopenX);
1271 return ERROR_DOS(ERRSRV,ERRaccess);
1275 /* XXXX we need to handle passed times, sattr and flags */
1276 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 END_PROFILE(SMBopenX);
1279 return ERROR_NT(status);
1282 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1284 unix_convert(fname,conn,0,&bad_path,&sbuf);
1286 END_PROFILE(SMBopenX);
1287 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1290 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1291 oplock_request, &rmode,&smb_action);
1294 END_PROFILE(SMBopenX);
1295 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1296 /* We have re-scheduled this call. */
1297 clear_cached_errors();
1300 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1303 size = sbuf.st_size;
1304 fmode = dos_mode(conn,fname,&sbuf);
1305 mtime = sbuf.st_mtime;
1307 close_file(fsp,False);
1308 END_PROFILE(SMBopenX);
1309 return ERROR_DOS(ERRDOS,ERRnoaccess);
1312 /* If the caller set the extended oplock request bit
1313 and we granted one (by whatever means) - set the
1314 correct bit for extended oplock reply.
1317 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1318 smb_action |= EXTENDED_OPLOCK_GRANTED;
1320 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1321 smb_action |= EXTENDED_OPLOCK_GRANTED;
1323 /* If the caller set the core oplock request bit
1324 and we granted one (by whatever means) - set the
1325 correct bit for core oplock reply.
1328 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1329 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1331 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1332 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1334 set_message(outbuf,15,0,True);
1335 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1336 SSVAL(outbuf,smb_vwv3,fmode);
1337 if(lp_dos_filetime_resolution(SNUM(conn)) )
1338 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1340 put_dos_date3(outbuf,smb_vwv4,mtime);
1341 SIVAL(outbuf,smb_vwv6,(uint32)size);
1342 SSVAL(outbuf,smb_vwv8,rmode);
1343 SSVAL(outbuf,smb_vwv11,smb_action);
1345 END_PROFILE(SMBopenX);
1346 return chain_reply(inbuf,outbuf,length,bufsize);
1349 /****************************************************************************
1350 Reply to a SMBulogoffX.
1351 ****************************************************************************/
1353 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1355 uint16 vuid = SVAL(inbuf,smb_uid);
1356 user_struct *vuser = get_valid_user_struct(vuid);
1357 START_PROFILE(SMBulogoffX);
1360 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1362 /* in user level security we are supposed to close any files
1363 open by this user */
1364 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1365 file_close_user(vuid);
1367 invalidate_vuid(vuid);
1369 set_message(outbuf,2,0,True);
1371 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1373 END_PROFILE(SMBulogoffX);
1374 return chain_reply(inbuf,outbuf,length,bufsize);
1377 /****************************************************************************
1378 Reply to a mknew or a create.
1379 ****************************************************************************/
1381 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1388 BOOL bad_path = False;
1390 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1391 SMB_STRUCT_STAT sbuf;
1393 START_PROFILE(SMBcreate);
1395 com = SVAL(inbuf,smb_com);
1397 createmode = SVAL(inbuf,smb_vwv0);
1398 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 END_PROFILE(SMBcreate);
1401 return ERROR_NT(status);
1404 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1406 unix_convert(fname,conn,0,&bad_path,&sbuf);
1408 END_PROFILE(SMBcreate);
1409 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1412 if (createmode & aVOLID)
1413 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1415 if(com == SMBmknew) {
1416 /* We should fail if file exists. */
1417 ofun = FILE_CREATE_IF_NOT_EXIST;
1419 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1420 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1423 /* Open file in dos compatibility share mode. */
1424 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1425 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1428 END_PROFILE(SMBcreate);
1429 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1430 /* We have re-scheduled this call. */
1431 clear_cached_errors();
1434 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1437 outsize = set_message(outbuf,1,0,True);
1438 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1440 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1441 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1443 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1444 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1446 DEBUG( 2, ( "new file %s\n", fname ) );
1447 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1449 END_PROFILE(SMBcreate);
1453 /****************************************************************************
1454 Reply to a create temporary file.
1455 ****************************************************************************/
1457 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1462 BOOL bad_path = False;
1464 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1466 SMB_STRUCT_STAT sbuf;
1469 unsigned int namelen;
1471 START_PROFILE(SMBctemp);
1473 createattr = SVAL(inbuf,smb_vwv0);
1474 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 END_PROFILE(SMBctemp);
1477 return ERROR_NT(status);
1480 pstrcat(fname,"/TMXXXXXX");
1482 pstrcat(fname,"TMXXXXXX");
1485 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1487 unix_convert(fname,conn,0,&bad_path,&sbuf);
1489 END_PROFILE(SMBctemp);
1490 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1493 tmpfd = smb_mkstemp(fname);
1495 END_PROFILE(SMBctemp);
1496 return(UNIXERROR(ERRDOS,ERRnoaccess));
1499 SMB_VFS_STAT(conn,fname,&sbuf);
1501 /* Open file in dos compatibility share mode. */
1502 /* We should fail if file does not exist. */
1503 fsp = open_file_shared(conn,fname,&sbuf,
1504 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1505 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1506 (uint32)createattr, oplock_request, NULL, NULL);
1508 /* close fd from smb_mkstemp() */
1512 END_PROFILE(SMBctemp);
1513 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1514 /* We have re-scheduled this call. */
1515 clear_cached_errors();
1518 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1521 outsize = set_message(outbuf,1,0,True);
1522 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1524 /* the returned filename is relative to the directory */
1525 s = strrchr_m(fname, '/');
1531 p = smb_buf(outbuf);
1533 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1534 thing in the byte section. JRA */
1535 SSVALS(p, 0, -1); /* what is this? not in spec */
1537 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1539 outsize = set_message_end(outbuf, p);
1541 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1542 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1544 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1545 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1547 DEBUG( 2, ( "created temp file %s\n", fname ) );
1548 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1549 fname, fsp->fd, sbuf.st_mode ) );
1551 END_PROFILE(SMBctemp);
1555 /*******************************************************************
1556 Check if a user is allowed to rename a file.
1557 ********************************************************************/
1559 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1566 if (!CAN_WRITE(conn))
1567 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1569 fmode = dos_mode(conn,fname,pst);
1570 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1571 return NT_STATUS_NO_SUCH_FILE;
1573 if (S_ISDIR(pst->st_mode))
1574 return NT_STATUS_OK;
1576 /* We need a better way to return NT status codes from open... */
1580 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1581 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1584 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1585 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1586 ret = NT_STATUS_SHARING_VIOLATION;
1589 unix_ERR_ntstatus = NT_STATUS_OK;
1592 close_file(fsp,False);
1593 return NT_STATUS_OK;
1596 /*******************************************************************
1597 Check if a user is allowed to delete a file.
1598 ********************************************************************/
1600 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1602 SMB_STRUCT_STAT sbuf;
1608 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1611 if (!CAN_WRITE(conn))
1612 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1614 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1615 if(errno == ENOENT) {
1617 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1619 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1621 return map_nt_error_from_unix(errno);
1624 fmode = dos_mode(conn,fname,&sbuf);
1626 /* Can't delete a directory. */
1628 return NT_STATUS_FILE_IS_A_DIRECTORY;
1630 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1631 return NT_STATUS_OBJECT_NAME_INVALID;
1632 #endif /* JRATEST */
1634 if (!lp_delete_readonly(SNUM(conn))) {
1636 return NT_STATUS_CANNOT_DELETE;
1638 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1639 return NT_STATUS_NO_SUCH_FILE;
1641 if (check_is_at_open) {
1642 if (!can_delete_file_in_directory(conn, fname)) {
1643 return NT_STATUS_ACCESS_DENIED;
1646 /* On open checks the open itself will check the share mode, so
1647 don't do it here as we'll get it wrong. */
1649 /* We need a better way to return NT status codes from open... */
1653 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1654 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1657 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1658 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1659 ret = unix_ERR_ntstatus;
1660 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1661 ret = NT_STATUS_SHARING_VIOLATION;
1664 unix_ERR_ntstatus = NT_STATUS_OK;
1667 close_file(fsp,False);
1669 return NT_STATUS_OK;
1672 /****************************************************************************
1673 The guts of the unlink command, split out so it may be called by the NT SMB
1675 ****************************************************************************/
1677 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1683 NTSTATUS error = NT_STATUS_OK;
1685 BOOL bad_path = False;
1687 SMB_STRUCT_STAT sbuf;
1689 *directory = *mask = 0;
1691 /* We must check for wildcards in the name given
1692 * directly by the client - before any unmangling.
1693 * This prevents an unmangling of a UNIX name containing
1694 * a DOS wildcard like '*' or '?' from unmangling into
1695 * a wildcard delete which was not intended.
1696 * FIX for #226. JRA.
1699 has_wild = ms_has_wild(name);
1701 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1703 p = strrchr_m(name,'/');
1705 pstrcpy(directory,".");
1709 pstrcpy(directory,name);
1714 * We should only check the mangled cache
1715 * here if unix_convert failed. This means
1716 * that the path in 'mask' doesn't exist
1717 * on the file system and so we need to look
1718 * for a possible mangle. This patch from
1719 * Tine Smukavec <valentin.smukavec@hermes.si>.
1722 if (!rc && mangle_is_mangled(mask))
1723 mangle_check_cache( mask, sizeof(pstring)-1 );
1726 pstrcat(directory,"/");
1727 pstrcat(directory,mask);
1728 error = can_delete(conn,directory,dirtype,bad_path,False);
1729 if (!NT_STATUS_IS_OK(error))
1732 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1736 struct smb_Dir *dir_hnd = NULL;
1739 if (check_name(directory,conn))
1740 dir_hnd = OpenDir(conn, directory);
1742 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1743 the pattern matches against the long name, otherwise the short name
1744 We don't implement this yet XXXX
1749 error = NT_STATUS_NO_SUCH_FILE;
1751 if (strequal(mask,"????????.???"))
1754 while ((dname = ReadDirName(dir_hnd, &offset))) {
1757 BOOL sys_direntry = False;
1758 pstrcpy(fname,dname);
1760 if (!is_visible_file(conn, directory, dname, &st, True)) {
1764 /* Quick check for "." and ".." */
1765 if (fname[0] == '.') {
1766 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1767 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1768 sys_direntry = True;
1775 if(!mask_match(fname, mask, conn->case_sensitive))
1779 error = NT_STATUS_OBJECT_NAME_INVALID;
1780 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1785 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1786 error = can_delete(conn,fname,dirtype,bad_path,False);
1787 if (!NT_STATUS_IS_OK(error)) {
1790 if (SMB_VFS_UNLINK(conn,fname) == 0)
1792 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1798 if (count == 0 && NT_STATUS_IS_OK(error)) {
1799 error = map_nt_error_from_unix(errno);
1805 /****************************************************************************
1807 ****************************************************************************/
1809 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1816 START_PROFILE(SMBunlink);
1818 dirtype = SVAL(inbuf,smb_vwv0);
1820 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 END_PROFILE(SMBunlink);
1823 return ERROR_NT(status);
1826 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1828 DEBUG(3,("reply_unlink : %s\n",name));
1830 status = unlink_internals(conn, dirtype, name);
1831 if (!NT_STATUS_IS_OK(status)) {
1832 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1833 /* We have re-scheduled this call. */
1834 clear_cached_errors();
1837 return ERROR_NT(status);
1841 * Win2k needs a changenotify request response before it will
1842 * update after a rename..
1844 process_pending_change_notify_queue((time_t)0);
1846 outsize = set_message(outbuf,0,0,True);
1848 END_PROFILE(SMBunlink);
1852 /****************************************************************************
1854 ****************************************************************************/
1856 static void fail_readraw(void)
1859 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1861 exit_server(errstr);
1864 #if defined(WITH_SENDFILE)
1865 /****************************************************************************
1866 Fake (read/write) sendfile. Returns -1 on read or write fail.
1867 ****************************************************************************/
1869 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1873 /* Paranioa check... */
1874 if (nread > bufsize) {
1879 ret = read_file(fsp,buf,startpos,nread);
1885 /* If we had a short read, fill with zeros. */
1887 memset(buf, '\0', nread - ret);
1890 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1894 return (ssize_t)nread;
1898 /****************************************************************************
1899 Use sendfile in readbraw.
1900 ****************************************************************************/
1902 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1903 ssize_t mincount, char *outbuf, int out_buffsize)
1907 #if defined(WITH_SENDFILE)
1909 * We can only use sendfile on a non-chained packet
1910 * but we can use on a non-oplocked file. tridge proved this
1911 * on a train in Germany :-). JRA.
1912 * reply_readbraw has already checked the length.
1915 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1918 _smb_setlen(outbuf,nread);
1919 header.data = outbuf;
1923 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1924 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1925 if (errno == ENOSYS) {
1926 goto normal_readbraw;
1930 * Special hack for broken Linux with no working sendfile. If we
1931 * return EINTR we sent the header but not the rest of the data.
1932 * Fake this up by doing read/write calls.
1934 if (errno == EINTR) {
1935 /* Ensure we don't do this again. */
1936 set_use_sendfile(SNUM(conn), False);
1937 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1939 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1940 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1941 fsp->fsp_name, strerror(errno) ));
1942 exit_server("send_file_readbraw fake_sendfile failed");
1947 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1948 fsp->fsp_name, strerror(errno) ));
1949 exit_server("send_file_readbraw sendfile failed");
1959 ret = read_file(fsp,outbuf+4,startpos,nread);
1960 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1969 _smb_setlen(outbuf,ret);
1970 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1974 /****************************************************************************
1975 Reply to a readbraw (core+ protocol).
1976 ****************************************************************************/
1978 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1980 extern struct current_user current_user;
1981 ssize_t maxcount,mincount;
1984 char *header = outbuf;
1986 START_PROFILE(SMBreadbraw);
1988 if (srv_is_signing_active()) {
1989 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1993 * Special check if an oplock break has been issued
1994 * and the readraw request croses on the wire, we must
1995 * return a zero length response here.
1998 if(global_oplock_break) {
1999 _smb_setlen(header,0);
2000 if (write_data(smbd_server_fd(),header,4) != 4)
2002 DEBUG(5,("readbraw - oplock break finished\n"));
2003 END_PROFILE(SMBreadbraw);
2007 fsp = file_fsp(inbuf,smb_vwv0);
2009 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2011 * fsp could be NULL here so use the value from the packet. JRA.
2013 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2014 _smb_setlen(header,0);
2015 if (write_data(smbd_server_fd(),header,4) != 4)
2017 END_PROFILE(SMBreadbraw);
2021 CHECK_FSP(fsp,conn);
2023 flush_write_cache(fsp, READRAW_FLUSH);
2025 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2026 if(CVAL(inbuf,smb_wct) == 10) {
2028 * This is a large offset (64 bit) read.
2030 #ifdef LARGE_SMB_OFF_T
2032 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2034 #else /* !LARGE_SMB_OFF_T */
2037 * Ensure we haven't been sent a >32 bit offset.
2040 if(IVAL(inbuf,smb_vwv8) != 0) {
2041 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2042 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2043 _smb_setlen(header,0);
2044 if (write_data(smbd_server_fd(),header,4) != 4)
2046 END_PROFILE(SMBreadbraw);
2050 #endif /* LARGE_SMB_OFF_T */
2053 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2054 _smb_setlen(header,0);
2055 if (write_data(smbd_server_fd(),header,4) != 4)
2057 END_PROFILE(SMBreadbraw);
2061 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2062 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2064 /* ensure we don't overrun the packet size */
2065 maxcount = MIN(65535,maxcount);
2067 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2068 SMB_OFF_T size = fsp->size;
2069 SMB_OFF_T sizeneeded = startpos + maxcount;
2071 if (size < sizeneeded) {
2073 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
2075 if (!fsp->can_write)
2079 if (startpos >= size)
2082 nread = MIN(maxcount,(size - startpos));
2085 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2086 if (nread < mincount)
2090 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2091 (int)maxcount, (int)mincount, (int)nread ) );
2093 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2095 DEBUG(5,("readbraw finished\n"));
2096 END_PROFILE(SMBreadbraw);
2100 /****************************************************************************
2101 Reply to a lockread (core+ protocol).
2102 ****************************************************************************/
2104 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2112 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2113 BOOL my_lock_ctx = False;
2114 START_PROFILE(SMBlockread);
2116 CHECK_FSP(fsp,conn);
2119 release_level_2_oplocks_on_change(fsp);
2121 numtoread = SVAL(inbuf,smb_vwv1);
2122 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2124 outsize = set_message(outbuf,5,3,True);
2125 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2126 data = smb_buf(outbuf) + 3;
2129 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2130 * protocol request that predates the read/write lock concept.
2131 * Thus instead of asking for a read lock here we need to ask
2132 * for a write lock. JRA.
2133 * Note that the requested lock size is unaffected by max_recv.
2136 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2137 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2139 if (NT_STATUS_V(status)) {
2142 * We used to make lockread a blocking lock. It turns out
2143 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2147 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2149 * A blocking lock was requested. Package up
2150 * this smb into a queued request and push it
2151 * onto the blocking lock queue.
2153 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2154 (SMB_BIG_UINT)numtoread)) {
2155 END_PROFILE(SMBlockread);
2160 END_PROFILE(SMBlockread);
2161 return ERROR_NT(status);
2165 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2168 if (numtoread > max_recv) {
2169 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2170 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2171 (unsigned int)numtoread, (unsigned int)max_recv ));
2172 numtoread = MIN(numtoread,max_recv);
2174 nread = read_file(fsp,data,startpos,numtoread);
2177 END_PROFILE(SMBlockread);
2178 return(UNIXERROR(ERRDOS,ERRnoaccess));
2182 SSVAL(outbuf,smb_vwv0,nread);
2183 SSVAL(outbuf,smb_vwv5,nread+3);
2184 SSVAL(smb_buf(outbuf),1,nread);
2186 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2187 fsp->fnum, (int)numtoread, (int)nread));
2189 END_PROFILE(SMBlockread);
2193 /****************************************************************************
2195 ****************************************************************************/
2197 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2204 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2205 START_PROFILE(SMBread);
2207 CHECK_FSP(fsp,conn);
2210 numtoread = SVAL(inbuf,smb_vwv1);
2211 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2213 outsize = set_message(outbuf,5,3,True);
2214 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2216 * The requested read size cannot be greater than max_recv. JRA.
2218 if (numtoread > max_recv) {
2219 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2220 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2221 (unsigned int)numtoread, (unsigned int)max_recv ));
2222 numtoread = MIN(numtoread,max_recv);
2225 data = smb_buf(outbuf) + 3;
2227 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2228 END_PROFILE(SMBread);
2229 return ERROR_DOS(ERRDOS,ERRlock);
2233 nread = read_file(fsp,data,startpos,numtoread);
2236 END_PROFILE(SMBread);
2237 return(UNIXERROR(ERRDOS,ERRnoaccess));
2241 SSVAL(outbuf,smb_vwv0,nread);
2242 SSVAL(outbuf,smb_vwv5,nread+3);
2243 SCVAL(smb_buf(outbuf),0,1);
2244 SSVAL(smb_buf(outbuf),1,nread);
2246 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2247 fsp->fnum, (int)numtoread, (int)nread ) );
2249 END_PROFILE(SMBread);
2253 /****************************************************************************
2254 Reply to a read and X - possibly using sendfile.
2255 ****************************************************************************/
2257 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2258 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2262 char *data = smb_buf(outbuf);
2264 #if defined(WITH_SENDFILE)
2266 * We can only use sendfile on a non-chained packet
2267 * but we can use on a non-oplocked file. tridge proved this
2268 * on a train in Germany :-). JRA.
2271 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2272 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2273 SMB_STRUCT_STAT sbuf;
2276 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2277 return(UNIXERROR(ERRDOS,ERRnoaccess));
2279 if (startpos > sbuf.st_size)
2282 if (smb_maxcnt > (sbuf.st_size - startpos))
2283 smb_maxcnt = (sbuf.st_size - startpos);
2285 if (smb_maxcnt == 0)
2289 * Set up the packet header before send. We
2290 * assume here the sendfile will work (get the
2291 * correct amount of data).
2294 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2295 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2296 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2297 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2298 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2299 SCVAL(outbuf,smb_vwv0,0xFF);
2300 set_message(outbuf,12,smb_maxcnt,False);
2301 header.data = outbuf;
2302 header.length = data - outbuf;
2305 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2306 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2307 if (errno == ENOSYS) {
2312 * Special hack for broken Linux with no working sendfile. If we
2313 * return EINTR we sent the header but not the rest of the data.
2314 * Fake this up by doing read/write calls.
2317 if (errno == EINTR) {
2318 /* Ensure we don't do this again. */
2319 set_use_sendfile(SNUM(conn), False);
2320 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2322 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2323 len_outbuf - (data-outbuf))) == -1) {
2324 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2325 fsp->fsp_name, strerror(errno) ));
2326 exit_server("send_file_readX: fake_sendfile failed");
2328 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2329 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2330 /* Returning -1 here means successful sendfile. */
2334 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2335 fsp->fsp_name, strerror(errno) ));
2336 exit_server("send_file_readX sendfile failed");
2339 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2340 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2341 /* Returning -1 here means successful sendfile. */
2349 nread = read_file(fsp,data,startpos,smb_maxcnt);
2352 END_PROFILE(SMBreadX);
2353 return(UNIXERROR(ERRDOS,ERRnoaccess));
2356 outsize = set_message(outbuf,12,nread,False);
2357 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2358 SSVAL(outbuf,smb_vwv5,nread);
2359 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2360 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2361 SSVAL(smb_buf(outbuf),-2,nread);
2363 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2364 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2366 /* Returning the number of bytes we want to send back - including header. */
2370 /****************************************************************************
2371 Reply to a read and X.
2372 ****************************************************************************/
2374 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2376 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2377 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2379 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2381 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2384 START_PROFILE(SMBreadX);
2386 /* If it's an IPC, pass off the pipe handler. */
2388 END_PROFILE(SMBreadX);
2389 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2392 CHECK_FSP(fsp,conn);
2395 set_message(outbuf,12,0,True);
2397 if (global_client_caps & CAP_LARGE_READX) {
2398 if (SVAL(inbuf,smb_vwv7) == 1) {
2399 smb_maxcnt |= (1<<16);
2401 if (smb_maxcnt > BUFFER_SIZE) {
2402 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2403 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2404 END_PROFILE(SMBreadX);
2405 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2409 if(CVAL(inbuf,smb_wct) == 12) {
2410 #ifdef LARGE_SMB_OFF_T
2412 * This is a large offset (64 bit) read.
2414 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2416 #else /* !LARGE_SMB_OFF_T */
2419 * Ensure we haven't been sent a >32 bit offset.
2422 if(IVAL(inbuf,smb_vwv10) != 0) {
2423 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2424 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2425 END_PROFILE(SMBreadX);
2426 return ERROR_DOS(ERRDOS,ERRbadaccess);
2429 #endif /* LARGE_SMB_OFF_T */
2433 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2434 END_PROFILE(SMBreadX);
2435 return ERROR_DOS(ERRDOS,ERRlock);
2438 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2440 nread = chain_reply(inbuf,outbuf,length,bufsize);
2442 END_PROFILE(SMBreadX);
2446 /****************************************************************************
2447 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2448 ****************************************************************************/
2450 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2453 ssize_t total_written=0;
2454 size_t numtowrite=0;
2459 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2461 START_PROFILE(SMBwritebraw);
2463 if (srv_is_signing_active()) {
2464 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2467 CHECK_FSP(fsp,conn);
2470 tcount = IVAL(inbuf,smb_vwv1);
2471 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2472 write_through = BITSETW(inbuf+smb_vwv7,0);
2474 /* We have to deal with slightly different formats depending
2475 on whether we are using the core+ or lanman1.0 protocol */
2477 if(Protocol <= PROTOCOL_COREPLUS) {
2478 numtowrite = SVAL(smb_buf(inbuf),-2);
2479 data = smb_buf(inbuf);
2481 numtowrite = SVAL(inbuf,smb_vwv10);
2482 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2485 /* force the error type */
2486 SCVAL(inbuf,smb_com,SMBwritec);
2487 SCVAL(outbuf,smb_com,SMBwritec);
2489 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2490 END_PROFILE(SMBwritebraw);
2491 return(ERROR_DOS(ERRDOS,ERRlock));
2495 nwritten = write_file(fsp,data,startpos,numtowrite);
2497 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2498 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2500 if (nwritten < (ssize_t)numtowrite) {
2501 END_PROFILE(SMBwritebraw);
2502 return(UNIXERROR(ERRHRD,ERRdiskfull));
2505 total_written = nwritten;
2507 /* Return a message to the redirector to tell it to send more bytes */
2508 SCVAL(outbuf,smb_com,SMBwritebraw);
2509 SSVALS(outbuf,smb_vwv0,-1);
2510 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2511 if (!send_smb(smbd_server_fd(),outbuf))
2512 exit_server("reply_writebraw: send_smb failed.");
2514 /* Now read the raw data into the buffer and write it */
2515 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2516 exit_server("secondary writebraw failed");
2519 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2520 numtowrite = smb_len(inbuf);
2522 /* Set up outbuf to return the correct return */
2523 outsize = set_message(outbuf,1,0,True);
2524 SCVAL(outbuf,smb_com,SMBwritec);
2525 SSVAL(outbuf,smb_vwv0,total_written);
2527 if (numtowrite != 0) {
2529 if (numtowrite > BUFFER_SIZE) {
2530 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2531 (unsigned int)numtowrite ));
2532 exit_server("secondary writebraw failed");
2535 if (tcount > nwritten+numtowrite) {
2536 DEBUG(3,("Client overestimated the write %d %d %d\n",
2537 (int)tcount,(int)nwritten,(int)numtowrite));
2540 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2541 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2543 exit_server("secondary writebraw failed");
2546 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2548 if (nwritten < (ssize_t)numtowrite) {
2549 SCVAL(outbuf,smb_rcls,ERRHRD);
2550 SSVAL(outbuf,smb_err,ERRdiskfull);
2554 total_written += nwritten;
2557 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2558 sync_file(conn,fsp);
2560 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2561 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2563 /* we won't return a status if write through is not selected - this follows what WfWg does */
2564 END_PROFILE(SMBwritebraw);
2565 if (!write_through && total_written==tcount) {
2567 #if RABBIT_PELLET_FIX
2569 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2570 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2572 if (!send_keepalive(smbd_server_fd()))
2573 exit_server("reply_writebraw: send of keepalive failed");
2581 /****************************************************************************
2582 Reply to a writeunlock (core+).
2583 ****************************************************************************/
2585 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2586 int size, int dum_buffsize)
2588 ssize_t nwritten = -1;
2592 NTSTATUS status = NT_STATUS_OK;
2593 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2595 START_PROFILE(SMBwriteunlock);
2597 CHECK_FSP(fsp,conn);
2600 numtowrite = SVAL(inbuf,smb_vwv1);
2601 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2602 data = smb_buf(inbuf) + 3;
2604 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2605 END_PROFILE(SMBwriteunlock);
2606 return ERROR_DOS(ERRDOS,ERRlock);
2609 /* The special X/Open SMB protocol handling of
2610 zero length writes is *NOT* done for
2615 nwritten = write_file(fsp,data,startpos,numtowrite);
2617 if (lp_syncalways(SNUM(conn)))
2618 sync_file(conn,fsp);
2620 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2621 END_PROFILE(SMBwriteunlock);
2622 return(UNIXERROR(ERRHRD,ERRdiskfull));
2626 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2627 (SMB_BIG_UINT)startpos);
2628 if (NT_STATUS_V(status)) {
2629 END_PROFILE(SMBwriteunlock);
2630 return ERROR_NT(status);
2634 outsize = set_message(outbuf,1,0,True);
2636 SSVAL(outbuf,smb_vwv0,nwritten);
2638 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2639 fsp->fnum, (int)numtowrite, (int)nwritten));
2641 END_PROFILE(SMBwriteunlock);
2645 /****************************************************************************
2647 ****************************************************************************/
2649 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2652 ssize_t nwritten = -1;
2655 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2657 START_PROFILE(SMBwrite);
2659 /* If it's an IPC, pass off the pipe handler. */
2661 END_PROFILE(SMBwrite);
2662 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2665 CHECK_FSP(fsp,conn);
2668 numtowrite = SVAL(inbuf,smb_vwv1);
2669 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2670 data = smb_buf(inbuf) + 3;
2672 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2673 END_PROFILE(SMBwrite);
2674 return ERROR_DOS(ERRDOS,ERRlock);
2678 * X/Open SMB protocol says that if smb_vwv1 is
2679 * zero then the file size should be extended or
2680 * truncated to the size given in smb_vwv[2-3].
2683 if(numtowrite == 0) {
2685 * This is actually an allocate call, and set EOF. JRA.
2687 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2689 END_PROFILE(SMBwrite);
2690 return ERROR_NT(NT_STATUS_DISK_FULL);
2692 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2694 END_PROFILE(SMBwrite);
2695 return ERROR_NT(NT_STATUS_DISK_FULL);
2698 nwritten = write_file(fsp,data,startpos,numtowrite);
2700 if (lp_syncalways(SNUM(conn)))
2701 sync_file(conn,fsp);
2703 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2704 END_PROFILE(SMBwrite);
2705 return(UNIXERROR(ERRHRD,ERRdiskfull));
2708 outsize = set_message(outbuf,1,0,True);
2710 SSVAL(outbuf,smb_vwv0,nwritten);
2712 if (nwritten < (ssize_t)numtowrite) {
2713 SCVAL(outbuf,smb_rcls,ERRHRD);
2714 SSVAL(outbuf,smb_err,ERRdiskfull);
2717 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2719 END_PROFILE(SMBwrite);
2723 /****************************************************************************
2724 Reply to a write and X.
2725 ****************************************************************************/
2727 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2729 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2730 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2731 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2732 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2733 ssize_t nwritten = -1;
2734 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2735 unsigned int smblen = smb_len(inbuf);
2737 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2738 START_PROFILE(SMBwriteX);
2740 /* If it's an IPC, pass off the pipe handler. */
2742 END_PROFILE(SMBwriteX);
2743 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2746 CHECK_FSP(fsp,conn);
2749 /* Deal with possible LARGE_WRITEX */
2751 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2753 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2754 END_PROFILE(SMBwriteX);
2755 return ERROR_DOS(ERRDOS,ERRbadmem);
2758 data = smb_base(inbuf) + smb_doff;
2760 if(CVAL(inbuf,smb_wct) == 14) {
2761 #ifdef LARGE_SMB_OFF_T
2763 * This is a large offset (64 bit) write.
2765 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2767 #else /* !LARGE_SMB_OFF_T */
2770 * Ensure we haven't been sent a >32 bit offset.
2773 if(IVAL(inbuf,smb_vwv12) != 0) {
2774 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2775 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2776 END_PROFILE(SMBwriteX);
2777 return ERROR_DOS(ERRDOS,ERRbadaccess);
2780 #endif /* LARGE_SMB_OFF_T */
2783 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2784 END_PROFILE(SMBwriteX);
2785 return ERROR_DOS(ERRDOS,ERRlock);
2788 /* X/Open SMB protocol says that, unlike SMBwrite
2789 if the length is zero then NO truncation is
2790 done, just a write of zero. To truncate a file,
2796 nwritten = write_file(fsp,data,startpos,numtowrite);
2798 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2799 END_PROFILE(SMBwriteX);
2800 return(UNIXERROR(ERRHRD,ERRdiskfull));
2803 set_message(outbuf,6,0,True);
2805 SSVAL(outbuf,smb_vwv2,nwritten);
2807 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2809 if (nwritten < (ssize_t)numtowrite) {
2810 SCVAL(outbuf,smb_rcls,ERRHRD);
2811 SSVAL(outbuf,smb_err,ERRdiskfull);
2814 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2815 fsp->fnum, (int)numtowrite, (int)nwritten));
2817 if (lp_syncalways(SNUM(conn)) || write_through)
2818 sync_file(conn,fsp);
2820 END_PROFILE(SMBwriteX);
2821 return chain_reply(inbuf,outbuf,length,bufsize);
2824 /****************************************************************************
2826 ****************************************************************************/
2828 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2834 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2835 START_PROFILE(SMBlseek);
2837 CHECK_FSP(fsp,conn);
2839 flush_write_cache(fsp, SEEK_FLUSH);
2841 mode = SVAL(inbuf,smb_vwv1) & 3;
2842 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2843 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2852 res = fsp->pos + startpos;
2863 if (umode == SEEK_END) {
2864 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2865 if(errno == EINVAL) {
2866 SMB_OFF_T current_pos = startpos;
2867 SMB_STRUCT_STAT sbuf;
2869 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2870 END_PROFILE(SMBlseek);
2871 return(UNIXERROR(ERRDOS,ERRnoaccess));
2874 current_pos += sbuf.st_size;
2876 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2881 END_PROFILE(SMBlseek);
2882 return(UNIXERROR(ERRDOS,ERRnoaccess));
2888 outsize = set_message(outbuf,2,0,True);
2889 SIVAL(outbuf,smb_vwv0,res);
2891 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2892 fsp->fnum, (double)startpos, (double)res, mode));
2894 END_PROFILE(SMBlseek);
2898 /****************************************************************************
2900 ****************************************************************************/
2902 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2904 int outsize = set_message(outbuf,0,0,True);
2905 uint16 fnum = SVAL(inbuf,smb_vwv0);
2906 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2907 START_PROFILE(SMBflush);
2910 CHECK_FSP(fsp,conn);
2913 file_sync_all(conn);
2915 sync_file(conn,fsp);
2918 DEBUG(3,("flush\n"));
2919 END_PROFILE(SMBflush);
2923 /****************************************************************************
2925 ****************************************************************************/
2927 int reply_exit(connection_struct *conn,
2928 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2931 START_PROFILE(SMBexit);
2933 file_close_pid(SVAL(inbuf,smb_pid));
2935 outsize = set_message(outbuf,0,0,True);
2937 DEBUG(3,("exit\n"));
2939 END_PROFILE(SMBexit);
2943 /****************************************************************************
2944 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2945 ****************************************************************************/
2947 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2950 extern struct current_user current_user;
2953 int32 eclass = 0, err = 0;
2954 files_struct *fsp = NULL;
2955 START_PROFILE(SMBclose);
2957 outsize = set_message(outbuf,0,0,True);
2959 /* If it's an IPC, pass off to the pipe handler. */
2961 END_PROFILE(SMBclose);
2962 return reply_pipe_close(conn, inbuf,outbuf);
2965 fsp = file_fsp(inbuf,smb_vwv0);
2968 * We can only use CHECK_FSP if we know it's not a directory.
2971 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2972 END_PROFILE(SMBclose);
2973 return ERROR_DOS(ERRDOS,ERRbadfid);
2976 if(fsp->is_directory) {
2978 * Special case - close NT SMB directory handle.
2980 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2981 close_file(fsp,True);
2984 * Close ordinary file.
2989 /* Save the name for time set in close. */
2990 pstrcpy( file_name, fsp->fsp_name);
2992 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2994 conn->num_files_open));
2997 * Take care of any time sent in the close.
3000 mtime = make_unix_date3(inbuf+smb_vwv1);
3001 fsp_set_pending_modtime(fsp, mtime);
3004 * close_file() returns the unix errno if an error
3005 * was detected on close - normally this is due to
3006 * a disk full error. If not then it was probably an I/O error.
3009 if((close_err = close_file(fsp,True)) != 0) {
3011 END_PROFILE(SMBclose);
3012 return (UNIXERROR(ERRHRD,ERRgeneral));
3016 /* We have a cached error */
3018 END_PROFILE(SMBclose);
3019 return ERROR_DOS(eclass,err);
3022 END_PROFILE(SMBclose);
3026 /****************************************************************************
3027 Reply to a writeclose (Core+ protocol).
3028 ****************************************************************************/
3030 int reply_writeclose(connection_struct *conn,
3031 char *inbuf,char *outbuf, int size, int dum_buffsize)
3034 ssize_t nwritten = -1;
3040 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3041 START_PROFILE(SMBwriteclose);
3043 CHECK_FSP(fsp,conn);
3046 numtowrite = SVAL(inbuf,smb_vwv1);
3047 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3048 mtime = make_unix_date3(inbuf+smb_vwv4);
3049 data = smb_buf(inbuf) + 1;
3051 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3052 END_PROFILE(SMBwriteclose);
3053 return ERROR_DOS(ERRDOS,ERRlock);
3056 nwritten = write_file(fsp,data,startpos,numtowrite);
3058 set_filetime(conn, fsp->fsp_name,mtime);
3061 * More insanity. W2K only closes the file if writelen > 0.
3066 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3068 close_err = close_file(fsp,True);
3071 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3072 fsp->fnum, (int)numtowrite, (int)nwritten,
3073 conn->num_files_open));
3075 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3076 END_PROFILE(SMBwriteclose);
3077 return(UNIXERROR(ERRHRD,ERRdiskfull));
3080 if(close_err != 0) {
3082 END_PROFILE(SMBwriteclose);
3083 return(UNIXERROR(ERRHRD,ERRgeneral));
3086 outsize = set_message(outbuf,1,0,True);
3088 SSVAL(outbuf,smb_vwv0,nwritten);
3089 END_PROFILE(SMBwriteclose);
3093 /****************************************************************************
3095 ****************************************************************************/
3097 int reply_lock(connection_struct *conn,
3098 char *inbuf,char *outbuf, int length, int dum_buffsize)
3100 int outsize = set_message(outbuf,0,0,True);
3101 SMB_BIG_UINT count,offset;
3103 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3104 BOOL my_lock_ctx = False;
3106 START_PROFILE(SMBlock);
3108 CHECK_FSP(fsp,conn);
3110 release_level_2_oplocks_on_change(fsp);
3112 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3113 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3115 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3116 fsp->fd, fsp->fnum, (double)offset, (double)count));
3118 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3119 if (NT_STATUS_V(status)) {
3121 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3122 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3124 * A blocking lock was requested. Package up
3125 * this smb into a queued request and push it
3126 * onto the blocking lock queue.
3128 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3129 END_PROFILE(SMBlock);
3134 END_PROFILE(SMBlock);
3135 return ERROR_NT(status);
3138 END_PROFILE(SMBlock);
3142 /****************************************************************************
3144 ****************************************************************************/
3146 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3149 int outsize = set_message(outbuf,0,0,True);
3150 SMB_BIG_UINT count,offset;
3152 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3153 START_PROFILE(SMBunlock);
3155 CHECK_FSP(fsp,conn);
3157 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3158 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3160 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3161 if (NT_STATUS_V(status)) {
3162 END_PROFILE(SMBunlock);
3163 return ERROR_NT(status);
3166 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3167 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3169 END_PROFILE(SMBunlock);
3173 /****************************************************************************
3175 ****************************************************************************/
3177 int reply_tdis(connection_struct *conn,
3178 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3180 int outsize = set_message(outbuf,0,0,True);
3182 START_PROFILE(SMBtdis);
3184 vuid = SVAL(inbuf,smb_uid);
3187 DEBUG(4,("Invalid connection in tdis\n"));
3188 END_PROFILE(SMBtdis);
3189 return ERROR_DOS(ERRSRV,ERRinvnid);
3194 close_cnum(conn,vuid);
3196 END_PROFILE(SMBtdis);
3200 /****************************************************************************
3202 ****************************************************************************/
3204 int reply_echo(connection_struct *conn,
3205 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3207 int smb_reverb = SVAL(inbuf,smb_vwv0);
3209 unsigned int data_len = smb_buflen(inbuf);
3210 int outsize = set_message(outbuf,1,data_len,True);
3211 START_PROFILE(SMBecho);
3213 if (data_len > BUFFER_SIZE) {
3214 DEBUG(0,("reply_echo: data_len too large.\n"));
3215 END_PROFILE(SMBecho);
3219 /* copy any incoming data back out */
3221 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3223 if (smb_reverb > 100) {
3224 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3228 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3229 SSVAL(outbuf,smb_vwv0,seq_num);
3231 smb_setlen(outbuf,outsize - 4);
3233 if (!send_smb(smbd_server_fd(),outbuf))
3234 exit_server("reply_echo: send_smb failed.");
3237 DEBUG(3,("echo %d times\n", smb_reverb));
3241 END_PROFILE(SMBecho);
3245 /****************************************************************************
3246 Reply to a printopen.
3247 ****************************************************************************/
3249 int reply_printopen(connection_struct *conn,
3250 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3254 START_PROFILE(SMBsplopen);
3256 if (!CAN_PRINT(conn)) {
3257 END_PROFILE(SMBsplopen);
3258 return ERROR_DOS(ERRDOS,ERRnoaccess);
3261 /* Open for exclusive use, write only. */
3262 fsp = print_fsp_open(conn, NULL);
3265 END_PROFILE(SMBsplopen);
3266 return(UNIXERROR(ERRDOS,ERRnoaccess));
3269 outsize = set_message(outbuf,1,0,True);
3270 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3272 DEBUG(3,("openprint fd=%d fnum=%d\n",
3273 fsp->fd, fsp->fnum));
3275 END_PROFILE(SMBsplopen);
3279 /****************************************************************************
3280 Reply to a printclose.
3281 ****************************************************************************/
3283 int reply_printclose(connection_struct *conn,
3284 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3286 int outsize = set_message(outbuf,0,0,True);
3287 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3289 START_PROFILE(SMBsplclose);
3291 CHECK_FSP(fsp,conn);
3293 if (!CAN_PRINT(conn)) {
3294 END_PROFILE(SMBsplclose);
3295 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3298 DEBUG(3,("printclose fd=%d fnum=%d\n",
3299 fsp->fd,fsp->fnum));
3301 close_err = close_file(fsp,True);
3303 if(close_err != 0) {
3305 END_PROFILE(SMBsplclose);
3306 return(UNIXERROR(ERRHRD,ERRgeneral));
3309 END_PROFILE(SMBsplclose);
3313 /****************************************************************************
3314 Reply to a printqueue.
3315 ****************************************************************************/
3317 int reply_printqueue(connection_struct *conn,
3318 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3320 int outsize = set_message(outbuf,2,3,True);
3321 int max_count = SVAL(inbuf,smb_vwv0);
3322 int start_index = SVAL(inbuf,smb_vwv1);
3323 START_PROFILE(SMBsplretq);
3325 /* we used to allow the client to get the cnum wrong, but that
3326 is really quite gross and only worked when there was only
3327 one printer - I think we should now only accept it if they
3328 get it right (tridge) */
3329 if (!CAN_PRINT(conn)) {
3330 END_PROFILE(SMBsplretq);
3331 return ERROR_DOS(ERRDOS,ERRnoaccess);
3334 SSVAL(outbuf,smb_vwv0,0);
3335 SSVAL(outbuf,smb_vwv1,0);
3336 SCVAL(smb_buf(outbuf),0,1);
3337 SSVAL(smb_buf(outbuf),1,0);
3339 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3340 start_index, max_count));
3343 print_queue_struct *queue = NULL;
3344 print_status_struct status;
3345 char *p = smb_buf(outbuf) + 3;
3346 int count = print_queue_status(SNUM(conn), &queue, &status);
3347 int num_to_get = ABS(max_count);
3348 int first = (max_count>0?start_index:start_index+max_count+1);
3354 num_to_get = MIN(num_to_get,count-first);
3357 for (i=first;i<first+num_to_get;i++) {
3358 put_dos_date2(p,0,queue[i].time);
3359 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3360 SSVAL(p,5, queue[i].job);
3361 SIVAL(p,7,queue[i].size);
3363 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3368 outsize = set_message(outbuf,2,28*count+3,False);
3369 SSVAL(outbuf,smb_vwv0,count);
3370 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3371 SCVAL(smb_buf(outbuf),0,1);
3372 SSVAL(smb_buf(outbuf),1,28*count);
3377 DEBUG(3,("%d entries returned in queue\n",count));
3380 END_PROFILE(SMBsplretq);
3384 /****************************************************************************
3385 Reply to a printwrite.
3386 ****************************************************************************/
3388 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3391 int outsize = set_message(outbuf,0,0,True);
3393 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3395 START_PROFILE(SMBsplwr);
3397 if (!CAN_PRINT(conn)) {
3398 END_PROFILE(SMBsplwr);
3399 return ERROR_DOS(ERRDOS,ERRnoaccess);
3402 CHECK_FSP(fsp,conn);
3405 numtowrite = SVAL(smb_buf(inbuf),1);
3406 data = smb_buf(inbuf) + 3;
3408 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3409 END_PROFILE(SMBsplwr);
3410 return(UNIXERROR(ERRHRD,ERRdiskfull));
3413 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3415 END_PROFILE(SMBsplwr);
3419 /****************************************************************************
3420 The guts of the mkdir command, split out so it may be called by the NT SMB
3422 ****************************************************************************/
3424 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3428 if(!CAN_WRITE(conn)) {
3429 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3431 return map_nt_error_from_unix(errno);
3434 /* The following 2 clauses set explicit DOS error codes. JRA. */
3435 if (ms_has_wild(directory)) {
3436 DEBUG(5,("mkdir_internal: failing create on filename %s with wildcards\n", directory));
3437 unix_ERR_class = ERRDOS;
3438 unix_ERR_code = ERRinvalidname;
3439 return NT_STATUS_OBJECT_NAME_INVALID;
3442 if( strchr_m(directory, ':')) {
3443 DEBUG(5,("mkdir_internal: failing create on filename %s with colon in name\n", directory));
3444 unix_ERR_class = ERRDOS;
3445 unix_ERR_code = ERRinvalidname;
3446 return NT_STATUS_NOT_A_DIRECTORY;
3450 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3453 if (!check_name(directory, conn)) {
3454 if(errno == ENOENT) {
3456 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3458 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3461 return map_nt_error_from_unix(errno);
3464 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3466 if(errno == ENOENT) {
3467 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3469 return map_nt_error_from_unix(errno);
3472 return NT_STATUS_OK;
3475 /****************************************************************************
3477 ****************************************************************************/
3479 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3484 BOOL bad_path = False;
3485 SMB_STRUCT_STAT sbuf;
3487 START_PROFILE(SMBmkdir);
3489 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3490 if (!NT_STATUS_IS_OK(status)) {
3491 END_PROFILE(SMBmkdir);
3492 return ERROR_NT(status);
3495 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3497 unix_convert(directory,conn,0,&bad_path,&sbuf);
3499 status = mkdir_internal(conn, directory,bad_path);
3500 if (!NT_STATUS_IS_OK(status)) {
3501 END_PROFILE(SMBmkdir);
3502 return ERROR_NT(status);
3505 if (lp_inherit_owner(SNUM(conn))) {
3506 /* Ensure we're checking for a symlink here.... */
3507 /* We don't want to get caught by a symlink racer. */
3509 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3510 END_PROFILE(SMBmkdir);
3511 return(UNIXERROR(ERRDOS,ERRnoaccess));
3514 if(!S_ISDIR(sbuf.st_mode)) {
3515 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3516 END_PROFILE(SMBmkdir);
3517 return(UNIXERROR(ERRDOS,ERRnoaccess));
3520 change_owner_to_parent(conn, NULL, directory, &sbuf);
3523 outsize = set_message(outbuf,0,0,True);
3525 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3527 END_PROFILE(SMBmkdir);
3531 /****************************************************************************
3532 Static function used by reply_rmdir to delete an entire directory
3533 tree recursively. Return False on ok, True on fail.
3534 ****************************************************************************/
3536 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3538 const char *dname = NULL;
3541 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3546 while((dname = ReadDirName(dir_hnd, &offset))) {
3550 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3553 if (!is_visible_file(conn, directory, dname, &st, False))
3556 /* Construct the full name. */
3557 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3563 pstrcpy(fullname, directory);
3564 pstrcat(fullname, "/");
3565 pstrcat(fullname, dname);
3567 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3572 if(st.st_mode & S_IFDIR) {
3573 if(recursive_rmdir(conn, fullname)!=0) {
3577 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3581 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3590 /****************************************************************************
3591 The internals of the rmdir code - called elsewhere.
3592 ****************************************************************************/
3594 BOOL rmdir_internals(connection_struct *conn, char *directory)
3599 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3600 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3602 * Check to see if the only thing in this directory are
3603 * vetoed files/directories. If so then delete them and
3604 * retry. If we fail to delete any of them (and we *don't*
3605 * do a recursive delete) then fail the rmdir.
3607 BOOL all_veto_files = True;
3609 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3611 if(dir_hnd != NULL) {
3612 long dirpos = TellDir(dir_hnd);
3613 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3614 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3616 if (!is_visible_file(conn, directory, dname, &st, False))
3618 if(!IS_VETO_PATH(conn, dname)) {
3619 all_veto_files = False;
3624 if(all_veto_files) {
3625 SeekDir(dir_hnd,dirpos);
3626 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3629 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3631 if (!is_visible_file(conn, directory, dname, &st, False))
3634 /* Construct the full name. */
3635 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3640 pstrcpy(fullname, directory);
3641 pstrcat(fullname, "/");
3642 pstrcat(fullname, dname);
3644 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3646 if(st.st_mode & S_IFDIR) {
3647 if(lp_recursive_veto_delete(SNUM(conn))) {
3648 if(recursive_rmdir(conn, fullname) != 0)
3651 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3653 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3657 /* Retry the rmdir */
3658 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3668 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3673 /****************************************************************************
3675 ****************************************************************************/
3677 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3682 BOOL bad_path = False;
3683 SMB_STRUCT_STAT sbuf;
3685 START_PROFILE(SMBrmdir);
3687 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3688 if (!NT_STATUS_IS_OK(status)) {
3689 END_PROFILE(SMBrmdir);
3690 return ERROR_NT(status);
3693 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3695 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3697 END_PROFILE(SMBrmdir);
3698 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3701 if (check_name(directory,conn)) {
3702 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3703 ok = rmdir_internals(conn, directory);
3707 END_PROFILE(SMBrmdir);
3708 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3711 outsize = set_message(outbuf,0,0,True);
3713 DEBUG( 3, ( "rmdir %s\n", directory ) );
3715 END_PROFILE(SMBrmdir);
3719 /*******************************************************************
3720 Resolve wildcards in a filename rename.
3721 Note that name is in UNIX charset and thus potentially can be more
3722 than fstring buffer (255 bytes) especially in default UTF-8 case.
3723 Therefore, we use pstring inside and all calls should ensure that
3724 name2 is at least pstring-long (they do already)
3725 ********************************************************************/
3727 static BOOL resolve_wildcards(const char *name1, char *name2)
3729 pstring root1,root2;
3731 char *p,*p2, *pname1, *pname2;
3732 int available_space, actual_space;
3735 pname1 = strrchr_m(name1,'/');
3736 pname2 = strrchr_m(name2,'/');
3738 if (!pname1 || !pname2)
3741 pstrcpy(root1,pname1);
3742 pstrcpy(root2,pname2);
3743 p = strrchr_m(root1,'.');
3750 p = strrchr_m(root2,'.');
3764 } else if (*p2 == '*') {
3780 } else if (*p2 == '*') {
3790 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3793 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3794 if (actual_space >= available_space - 1) {
3795 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3796 actual_space - available_space));
3799 pstrcpy_base(pname2, root2, name2);
3805 /****************************************************************************
3806 Ensure open files have their names updates.
3807 ****************************************************************************/
3809 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3812 BOOL did_rename = False;
3814 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3815 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3816 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3817 fsp->fsp_name, newname ));
3818 string_set(&fsp->fsp_name, newname);
3823 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3824 (unsigned int)dev, (double)inode, newname ));
3827 /****************************************************************************
3828 Rename an open file - given an fsp.
3829 ****************************************************************************/
3831 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3833 SMB_STRUCT_STAT sbuf;
3834 BOOL bad_path = False;
3835 pstring newname_last_component;
3836 NTSTATUS error = NT_STATUS_OK;
3841 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3843 /* Quick check for "." and ".." */
3844 if (!bad_path && newname_last_component[0] == '.') {
3845 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3846 return NT_STATUS_ACCESS_DENIED;
3849 if (!rcdest && bad_path) {
3850 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3853 /* Ensure newname contains a '/' */
3854 if(strrchr_m(newname,'/') == 0) {
3857 pstrcpy(tmpstr, "./");
3858 pstrcat(tmpstr, newname);
3859 pstrcpy(newname, tmpstr);
3863 * Check for special case with case preserving and not
3864 * case sensitive. If the old last component differs from the original
3865 * last component only by case, then we should allow
3866 * the rename (user is trying to change the case of the
3870 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3871 strequal(newname, fsp->fsp_name)) {
3873 pstring newname_modified_last_component;
3876 * Get the last component of the modified name.
3877 * Note that we guarantee that newname contains a '/'
3880 p = strrchr_m(newname,'/');
3881 pstrcpy(newname_modified_last_component,p+1);
3883 if(strcsequal(newname_modified_last_component,
3884 newname_last_component) == False) {
3886 * Replace the modified last component with
3889 pstrcpy(p+1, newname_last_component);
3894 * If the src and dest names are identical - including case,
3895 * don't do the rename, just return success.
3898 if (strcsequal(fsp->fsp_name, newname)) {
3899 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3901 return NT_STATUS_OK;
3904 dest_exists = vfs_object_exist(conn,newname,NULL);
3906 if(!replace_if_exists && dest_exists) {
3907 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3908 fsp->fsp_name,newname));
3909 return NT_STATUS_OBJECT_NAME_COLLISION;
3912 error = can_rename(conn,newname,attrs,&sbuf);
3914 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3915 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3916 nt_errstr(error), fsp->fsp_name,newname));
3917 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3918 error = NT_STATUS_ACCESS_DENIED;
3922 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3923 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3924 fsp->fsp_name,newname));
3925 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3926 return NT_STATUS_OK;
3929 if (errno == ENOTDIR || errno == EISDIR)
3930 error = NT_STATUS_OBJECT_NAME_COLLISION;
3932 error = map_nt_error_from_unix(errno);
3934 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3935 nt_errstr(error), fsp->fsp_name,newname));
3940 /****************************************************************************
3941 The guts of the rename command, split out so it may be called by the NT SMB
3943 ****************************************************************************/
3945 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3949 pstring last_component_src;
3950 pstring last_component_dest;
3953 BOOL bad_path_src = False;
3954 BOOL bad_path_dest = False;
3956 NTSTATUS error = NT_STATUS_OK;
3959 SMB_STRUCT_STAT sbuf1, sbuf2;
3961 *directory = *mask = 0;
3966 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3967 if (!rc && bad_path_src) {
3968 if (ms_has_wild(last_component_src))
3969 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3970 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3973 /* Quick check for "." and ".." */
3974 if (last_component_src[0] == '.') {
3975 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3976 return NT_STATUS_OBJECT_NAME_INVALID;
3980 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3982 /* Quick check for "." and ".." */
3983 if (last_component_dest[0] == '.') {
3984 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3985 return NT_STATUS_OBJECT_NAME_INVALID;
3990 * Split the old name into directory and last component
3991 * strings. Note that unix_convert may have stripped off a
3992 * leading ./ from both name and newname if the rename is
3993 * at the root of the share. We need to make sure either both
3994 * name and newname contain a / character or neither of them do
3995 * as this is checked in resolve_wildcards().
3998 p = strrchr_m(name,'/');
4000 pstrcpy(directory,".");
4004 pstrcpy(directory,name);
4006 *p = '/'; /* Replace needed for exceptional test below. */
4010 * We should only check the mangled cache
4011 * here if unix_convert failed. This means
4012 * that the path in 'mask' doesn't exist
4013 * on the file system and so we need to look
4014 * for a possible mangle. This patch from
4015 * Tine Smukavec <valentin.smukavec@hermes.si>.
4018 if (!rc && mangle_is_mangled(mask))
4019 mangle_check_cache( mask, sizeof(pstring)-1 );
4021 has_wild = ms_has_wild(mask);
4025 * No wildcards - just process the one file.
4027 BOOL is_short_name = mangle_is_8_3(name, True);
4029 /* Add a terminating '/' to the directory name. */
4030 pstrcat(directory,"/");
4031 pstrcat(directory,mask);
4033 /* Ensure newname contains a '/' also */
4034 if(strrchr_m(newname,'/') == 0) {
4037 pstrcpy(tmpstr, "./");
4038 pstrcat(tmpstr, newname);
4039 pstrcpy(newname, tmpstr);
4042 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4043 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4044 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4045 newname, last_component_dest, is_short_name));
4048 * Check for special case with case preserving and not
4049 * case sensitive, if directory and newname are identical,
4050 * and the old last component differs from the original
4051 * last component only by case, then we should allow
4052 * the rename (user is trying to change the case of the
4055 if((conn->case_sensitive == False) &&
4056 (((conn->case_preserve == True) &&
4057 (is_short_name == False)) ||
4058 ((conn->short_case_preserve == True) &&
4059 (is_short_name == True))) &&
4060 strcsequal(directory, newname)) {
4061 pstring modified_last_component;
4064 * Get the last component of the modified name.
4065 * Note that we guarantee that newname contains a '/'
4068 p = strrchr_m(newname,'/');
4069 pstrcpy(modified_last_component,p+1);
4071 if(strcsequal(modified_last_component,
4072 last_component_dest) == False) {
4074 * Replace the modified last component with
4077 pstrcpy(p+1, last_component_dest);
4081 resolve_wildcards(directory,newname);
4084 * The source object must exist.
4087 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4088 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4089 directory,newname));
4091 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4093 * Must return different errors depending on whether the parent
4094 * directory existed or not.
4097 p = strrchr_m(directory, '/');
4099 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4101 if (vfs_object_exist(conn, directory, NULL))
4102 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4103 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4105 error = map_nt_error_from_unix(errno);
4106 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4107 nt_errstr(error), directory,newname));
4112 if (!rcdest && bad_path_dest) {
4113 if (ms_has_wild(last_component_dest))
4114 return NT_STATUS_OBJECT_NAME_INVALID;
4115 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4118 error = can_rename(conn,directory,attrs,&sbuf1);
4120 if (!NT_STATUS_IS_OK(error)) {
4121 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4122 nt_errstr(error), directory,newname));
4127 * If the src and dest names are identical - including case,
4128 * don't do the rename, just return success.
4131 if (strcsequal(directory, newname)) {
4132 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4133 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4134 return NT_STATUS_OK;
4137 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4138 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4139 directory,newname));
4140 return NT_STATUS_OBJECT_NAME_COLLISION;
4143 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4144 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4145 directory,newname));
4146 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4147 return NT_STATUS_OK;
4150 if (errno == ENOTDIR || errno == EISDIR)
4151 error = NT_STATUS_OBJECT_NAME_COLLISION;
4153 error = map_nt_error_from_unix(errno);
4155 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4156 nt_errstr(error), directory,newname));
4161 * Wildcards - process each file that matches.
4163 struct smb_Dir *dir_hnd = NULL;
4167 if (check_name(directory,conn))
4168 dir_hnd = OpenDir(conn, directory);
4172 error = NT_STATUS_NO_SUCH_FILE;
4173 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4175 if (strequal(mask,"????????.???"))
4178 while ((dname = ReadDirName(dir_hnd, &offset))) {
4180 BOOL sysdir_entry = False;
4182 pstrcpy(fname,dname);
4184 /* Quick check for "." and ".." */
4185 if (fname[0] == '.') {
4186 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4188 sysdir_entry = True;
4195 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4198 if(!mask_match(fname, mask, conn->case_sensitive))
4202 error = NT_STATUS_OBJECT_NAME_INVALID;
4206 error = NT_STATUS_ACCESS_DENIED;
4207 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4208 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4209 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4210 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4213 error = can_rename(conn,fname,attrs,&sbuf1);
4214 if (!NT_STATUS_IS_OK(error)) {
4215 DEBUG(6,("rename %s refused\n", fname));
4218 pstrcpy(destname,newname);
4220 if (!resolve_wildcards(fname,destname)) {
4221 DEBUG(6,("resolve_wildcards %s %s failed\n",
4226 if (strcsequal(fname,destname)) {
4227 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4228 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4230 error = NT_STATUS_OK;
4234 if (!replace_if_exists &&
4235 vfs_file_exist(conn,destname, NULL)) {
4236 DEBUG(6,("file_exist %s\n", destname));
4237 error = NT_STATUS_OBJECT_NAME_COLLISION;
4241 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4242 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4244 error = NT_STATUS_OK;
4246 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4251 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4252 if (!rcdest && bad_path_dest) {
4253 if (ms_has_wild(last_component_dest))
4254 return NT_STATUS_OBJECT_NAME_INVALID;
4255 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4260 if (count == 0 && NT_STATUS_IS_OK(error)) {
4261 error = map_nt_error_from_unix(errno);
4267 /****************************************************************************
4269 ****************************************************************************/
4271 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4278 uint16 attrs = SVAL(inbuf,smb_vwv0);
4281 START_PROFILE(SMBmv);
4283 p = smb_buf(inbuf) + 1;
4284 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4285 if (!NT_STATUS_IS_OK(status)) {
4287 return ERROR_NT(status);
4290 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4291 if (!NT_STATUS_IS_OK(status)) {
4293 return ERROR_NT(status);
4296 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4297 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4299 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4301 status = rename_internals(conn, name, newname, attrs, False);
4302 if (!NT_STATUS_IS_OK(status)) {
4304 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4305 /* We have re-scheduled this call. */
4306 clear_cached_errors();
4309 return ERROR_NT(status);
4313 * Win2k needs a changenotify request response before it will
4314 * update after a rename..
4316 process_pending_change_notify_queue((time_t)0);
4317 outsize = set_message(outbuf,0,0,True);
4323 /*******************************************************************
4324 Copy a file as part of a reply_copy.
4325 ******************************************************************/
4327 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4328 int count,BOOL target_is_directory, int *err_ret)
4331 SMB_STRUCT_STAT src_sbuf, sbuf2;
4333 files_struct *fsp1,*fsp2;
4339 pstrcpy(dest,dest1);
4340 if (target_is_directory) {
4341 char *p = strrchr_m(src,'/');
4350 if (!vfs_file_exist(conn,src,&src_sbuf))
4353 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4354 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4360 if (!target_is_directory && count)
4361 ofun = FILE_EXISTS_OPEN;
4363 dosattrs = dos_mode(conn, src, &src_sbuf);
4364 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4365 ZERO_STRUCTP(&sbuf2);
4367 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4368 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4371 close_file(fsp1,False);
4375 if ((ofun&3) == 1) {
4376 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4377 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4379 * Stop the copy from occurring.
4382 src_sbuf.st_size = 0;
4386 if (src_sbuf.st_size)
4387 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4389 close_file(fsp1,False);
4391 /* Ensure the modtime is set correctly on the destination file. */
4392 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4395 * As we are opening fsp1 read-only we only expect
4396 * an error on close on fsp2 if we are out of space.
4397 * Thus we don't look at the error return from the
4400 *err_ret = close_file(fsp2,False);
4402 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4405 /****************************************************************************
4406 Reply to a file copy.
4407 ****************************************************************************/
4409 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4414 pstring mask,newname;
4417 int error = ERRnoaccess;
4421 int tid2 = SVAL(inbuf,smb_vwv0);
4422 int ofun = SVAL(inbuf,smb_vwv1);
4423 int flags = SVAL(inbuf,smb_vwv2);
4424 BOOL target_is_directory=False;
4425 BOOL bad_path1 = False;
4426 BOOL bad_path2 = False;
4428 SMB_STRUCT_STAT sbuf1, sbuf2;
4431 START_PROFILE(SMBcopy);
4433 *directory = *mask = 0;
4436 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4437 if (!NT_STATUS_IS_OK(status)) {
4438 END_PROFILE(SMBcopy);
4439 return ERROR_NT(status);
4441 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4442 if (!NT_STATUS_IS_OK(status)) {
4443 END_PROFILE(SMBcopy);
4444 return ERROR_NT(status);
4447 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4449 if (tid2 != conn->cnum) {
4450 /* can't currently handle inter share copies XXXX */
4451 DEBUG(3,("Rejecting inter-share copy\n"));
4452 END_PROFILE(SMBcopy);
4453 return ERROR_DOS(ERRSRV,ERRinvdevice);
4456 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4457 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4459 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4460 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4462 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4464 if ((flags&1) && target_is_directory) {
4465 END_PROFILE(SMBcopy);
4466 return ERROR_DOS(ERRDOS,ERRbadfile);
4469 if ((flags&2) && !target_is_directory) {
4470 END_PROFILE(SMBcopy);
4471 return ERROR_DOS(ERRDOS,ERRbadpath);
4474 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4475 /* wants a tree copy! XXXX */
4476 DEBUG(3,("Rejecting tree copy\n"));
4477 END_PROFILE(SMBcopy);
4478 return ERROR_DOS(ERRSRV,ERRerror);
4481 p = strrchr_m(name,'/');
4483 pstrcpy(directory,"./");
4487 pstrcpy(directory,name);
4492 * We should only check the mangled cache
4493 * here if unix_convert failed. This means
4494 * that the path in 'mask' doesn't exist
4495 * on the file system and so we need to look
4496 * for a possible mangle. This patch from
4497 * Tine Smukavec <valentin.smukavec@hermes.si>.
4500 if (!rc && mangle_is_mangled(mask))
4501 mangle_check_cache( mask, sizeof(pstring)-1 );
4503 has_wild = ms_has_wild(mask);
4506 pstrcat(directory,"/");
4507 pstrcat(directory,mask);
4508 if (resolve_wildcards(directory,newname) &&
4509 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4513 END_PROFILE(SMBcopy);
4514 return(UNIXERROR(ERRHRD,ERRgeneral));
4517 exists = vfs_file_exist(conn,directory,NULL);
4520 struct smb_Dir *dir_hnd = NULL;
4524 if (check_name(directory,conn))
4525 dir_hnd = OpenDir(conn, directory);
4531 if (strequal(mask,"????????.???"))
4534 while ((dname = ReadDirName(dir_hnd, &offset))) {
4536 pstrcpy(fname,dname);
4538 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4541 if(!mask_match(fname, mask, conn->case_sensitive))
4544 error = ERRnoaccess;
4545 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4546 pstrcpy(destname,newname);
4547 if (resolve_wildcards(fname,destname) &&
4548 copy_file(fname,destname,conn,ofun,
4549 count,target_is_directory,&err))
4551 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4559 /* Error on close... */
4561 END_PROFILE(SMBcopy);
4562 return(UNIXERROR(ERRHRD,ERRgeneral));
4566 END_PROFILE(SMBcopy);
4567 return ERROR_DOS(ERRDOS,error);
4569 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4570 unix_ERR_class = ERRDOS;
4571 unix_ERR_code = ERRbadpath;
4573 END_PROFILE(SMBcopy);
4574 return(UNIXERROR(ERRDOS,error));
4578 outsize = set_message(outbuf,1,0,True);
4579 SSVAL(outbuf,smb_vwv0,count);
4581 END_PROFILE(SMBcopy);
4585 /****************************************************************************
4587 ****************************************************************************/
4589 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4597 START_PROFILE(pathworks_setdir);
4600 if (!CAN_SETDIR(snum)) {
4601 END_PROFILE(pathworks_setdir);
4602 return ERROR_DOS(ERRDOS,ERRnoaccess);
4605 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4606 if (!NT_STATUS_IS_OK(status)) {
4607 END_PROFILE(pathworks_setdir);
4608 return ERROR_NT(status);
4611 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4613 if (strlen(newdir) == 0) {
4616 ok = vfs_directory_exist(conn,newdir,NULL);
4618 string_set(&conn->connectpath,newdir);
4622 END_PROFILE(pathworks_setdir);
4623 return ERROR_DOS(ERRDOS,ERRbadpath);
4626 outsize = set_message(outbuf,0,0,True);
4627 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4629 DEBUG(3,("setdir %s\n", newdir));
4631 END_PROFILE(pathworks_setdir);
4635 /****************************************************************************
4636 Get a lock pid, dealing with large count requests.
4637 ****************************************************************************/
4639 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4641 if(!large_file_format)
4642 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4644 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4647 /****************************************************************************
4648 Get a lock count, dealing with large count requests.
4649 ****************************************************************************/
4651 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4653 SMB_BIG_UINT count = 0;
4655 if(!large_file_format) {
4656 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4659 #if defined(HAVE_LONGLONG)
4660 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4661 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4662 #else /* HAVE_LONGLONG */
4665 * NT4.x seems to be broken in that it sends large file (64 bit)
4666 * lockingX calls even if the CAP_LARGE_FILES was *not*
4667 * negotiated. For boxes without large unsigned ints truncate the
4668 * lock count by dropping the top 32 bits.
4671 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4672 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4673 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4674 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4675 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4678 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4679 #endif /* HAVE_LONGLONG */
4685 #if !defined(HAVE_LONGLONG)
4686 /****************************************************************************
4687 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4688 ****************************************************************************/
4690 static uint32 map_lock_offset(uint32 high, uint32 low)
4694 uint32 highcopy = high;
4697 * Try and find out how many significant bits there are in high.
4700 for(i = 0; highcopy; i++)
4704 * We use 31 bits not 32 here as POSIX
4705 * lock offsets may not be negative.
4708 mask = (~0) << (31 - i);
4711 return 0; /* Fail. */
4717 #endif /* !defined(HAVE_LONGLONG) */
4719 /****************************************************************************
4720 Get a lock offset, dealing with large offset requests.
4721 ****************************************************************************/
4723 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4725 SMB_BIG_UINT offset = 0;
4729 if(!large_file_format) {
4730 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4733 #if defined(HAVE_LONGLONG)
4734 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4735 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4736 #else /* HAVE_LONGLONG */
4739 * NT4.x seems to be broken in that it sends large file (64 bit)
4740 * lockingX calls even if the CAP_LARGE_FILES was *not*
4741 * negotiated. For boxes without large unsigned ints mangle the
4742 * lock offset by mapping the top 32 bits onto the lower 32.
4745 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4746 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4747 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4750 if((new_low = map_lock_offset(high, low)) == 0) {
4752 return (SMB_BIG_UINT)-1;
4755 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4756 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4757 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4758 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4761 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4762 #endif /* HAVE_LONGLONG */
4768 /****************************************************************************
4769 Reply to a lockingX request.
4770 ****************************************************************************/
4772 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4774 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4775 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4776 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4777 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4778 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4779 SMB_BIG_UINT count = 0, offset = 0;
4781 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4784 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4786 BOOL my_lock_ctx = False;
4789 START_PROFILE(SMBlockingX);
4791 CHECK_FSP(fsp,conn);
4793 data = smb_buf(inbuf);
4795 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4796 /* we don't support these - and CANCEL_LOCK makes w2k
4797 and XP reboot so I don't really want to be
4798 compatible! (tridge) */
4799 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4802 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4803 /* Need to make this like a cancel.... JRA. */
4804 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4807 /* Check if this is an oplock break on a file
4808 we have granted an oplock on.
4810 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4811 /* Client can insist on breaking to none. */
4812 BOOL break_to_none = (oplocklevel == 0);
4814 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4815 (unsigned int)oplocklevel, fsp->fnum ));
4818 * Make sure we have granted an exclusive or batch oplock on this file.
4821 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4822 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4823 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4825 /* if this is a pure oplock break request then don't send a reply */
4826 if (num_locks == 0 && num_ulocks == 0) {
4827 END_PROFILE(SMBlockingX);
4830 END_PROFILE(SMBlockingX);
4831 return ERROR_DOS(ERRDOS,ERRlock);
4835 if (remove_oplock(fsp, break_to_none) == False) {
4836 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4840 /* if this is a pure oplock break request then don't send a reply */
4841 if (num_locks == 0 && num_ulocks == 0) {
4842 /* Sanity check - ensure a pure oplock break is not a
4844 if(CVAL(inbuf,smb_vwv0) != 0xff)
4845 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4846 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4847 END_PROFILE(SMBlockingX);
4853 * We do this check *after* we have checked this is not a oplock break
4854 * response message. JRA.
4857 release_level_2_oplocks_on_change(fsp);
4859 /* Data now points at the beginning of the list
4860 of smb_unlkrng structs */
4861 for(i = 0; i < (int)num_ulocks; i++) {
4862 lock_pid = get_lock_pid( data, i, large_file_format);
4863 count = get_lock_count( data, i, large_file_format);
4864 offset = get_lock_offset( data, i, large_file_format, &err);
4867 * There is no error code marked "stupid client bug".... :-).
4870 END_PROFILE(SMBlockingX);
4871 return ERROR_DOS(ERRDOS,ERRnoaccess);
4874 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4875 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4877 status = do_unlock(fsp,conn,lock_pid,count,offset);
4878 if (NT_STATUS_V(status)) {
4879 END_PROFILE(SMBlockingX);
4880 return ERROR_NT(status);
4884 /* Setup the timeout in seconds. */
4886 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4888 /* Now do any requested locks */
4889 data += ((large_file_format ? 20 : 10)*num_ulocks);
4891 /* Data now points at the beginning of the list
4892 of smb_lkrng structs */
4894 for(i = 0; i < (int)num_locks; i++) {
4895 lock_pid = get_lock_pid( data, i, large_file_format);
4896 count = get_lock_count( data, i, large_file_format);
4897 offset = get_lock_offset( data, i, large_file_format, &err);
4900 * There is no error code marked "stupid client bug".... :-).
4903 END_PROFILE(SMBlockingX);
4904 return ERROR_DOS(ERRDOS,ERRnoaccess);
4907 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4908 (double)offset, (double)count, (unsigned int)lock_pid,
4909 fsp->fsp_name, (int)lock_timeout ));
4911 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4912 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4913 if (NT_STATUS_V(status)) {
4915 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4916 * Even if it's our own lock context, we need to wait here as
4917 * there may be an unlock on the way.
4918 * So I removed a "&& !my_lock_ctx" from the following
4919 * if statement. JRA.
4921 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4923 * A blocking lock was requested. Package up
4924 * this smb into a queued request and push it
4925 * onto the blocking lock queue.
4927 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4928 END_PROFILE(SMBlockingX);
4936 /* If any of the above locks failed, then we must unlock
4937 all of the previous locks (X/Open spec). */
4938 if (i != num_locks && num_locks != 0) {
4940 * Ensure we don't do a remove on the lock that just failed,
4941 * as under POSIX rules, if we have a lock already there, we
4942 * will delete it (and we shouldn't) .....
4944 for(i--; i >= 0; i--) {
4945 lock_pid = get_lock_pid( data, i, large_file_format);
4946 count = get_lock_count( data, i, large_file_format);
4947 offset = get_lock_offset( data, i, large_file_format, &err);
4950 * There is no error code marked "stupid client bug".... :-).
4953 END_PROFILE(SMBlockingX);
4954 return ERROR_DOS(ERRDOS,ERRnoaccess);
4957 do_unlock(fsp,conn,lock_pid,count,offset);
4959 END_PROFILE(SMBlockingX);
4960 return ERROR_NT(status);
4963 set_message(outbuf,2,0,True);
4965 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4966 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4968 END_PROFILE(SMBlockingX);
4969 return chain_reply(inbuf,outbuf,length,bufsize);
4972 /****************************************************************************
4973 Reply to a SMBreadbmpx (read block multiplex) request.
4974 ****************************************************************************/
4976 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4987 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4988 START_PROFILE(SMBreadBmpx);
4990 /* this function doesn't seem to work - disable by default */
4991 if (!lp_readbmpx()) {
4992 END_PROFILE(SMBreadBmpx);
4993 return ERROR_DOS(ERRSRV,ERRuseSTD);
4996 outsize = set_message(outbuf,8,0,True);
4998 CHECK_FSP(fsp,conn);
5001 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5002 maxcount = SVAL(inbuf,smb_vwv3);
5004 data = smb_buf(outbuf);
5005 pad = ((long)data)%4;
5010 max_per_packet = bufsize-(outsize+pad);
5014 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5015 END_PROFILE(SMBreadBmpx);
5016 return ERROR_DOS(ERRDOS,ERRlock);
5020 size_t N = MIN(max_per_packet,tcount-total_read);
5022 nread = read_file(fsp,data,startpos,N);
5027 if (nread < (ssize_t)N)
5028 tcount = total_read + nread;
5030 set_message(outbuf,8,nread,False);
5031 SIVAL(outbuf,smb_vwv0,startpos);
5032 SSVAL(outbuf,smb_vwv2,tcount);
5033 SSVAL(outbuf,smb_vwv6,nread);
5034 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5036 if (!send_smb(smbd_server_fd(),outbuf))
5037 exit_server("reply_readbmpx: send_smb failed.");
5039 total_read += nread;
5041 } while (total_read < (ssize_t)tcount);
5043 END_PROFILE(SMBreadBmpx);
5047 /****************************************************************************
5048 Reply to a SMBsetattrE.
5049 ****************************************************************************/
5051 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5053 struct utimbuf unix_times;
5055 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5056 START_PROFILE(SMBsetattrE);
5058 outsize = set_message(outbuf,0,0,True);
5060 if(!fsp || (fsp->conn != conn)) {
5061 END_PROFILE(SMBgetattrE);
5062 return ERROR_DOS(ERRDOS,ERRbadfid);
5066 * Convert the DOS times into unix times. Ignore create
5067 * time as UNIX can't set this.
5070 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5071 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5074 * Patch from Ray Frush <frush@engr.colostate.edu>
5075 * Sometimes times are sent as zero - ignore them.
5078 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5079 /* Ignore request */
5080 if( DEBUGLVL( 3 ) ) {
5081 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5082 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5084 END_PROFILE(SMBsetattrE);
5086 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5087 /* set modify time = to access time if modify time was unset */
5088 unix_times.modtime = unix_times.actime;
5091 /* Set the date on this file */
5092 /* Should we set pending modtime here ? JRA */
5093 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5094 END_PROFILE(SMBsetattrE);
5095 return ERROR_DOS(ERRDOS,ERRnoaccess);
5098 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5099 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5101 END_PROFILE(SMBsetattrE);
5106 /* Back from the dead for OS/2..... JRA. */
5108 /****************************************************************************
5109 Reply to a SMBwritebmpx (write block multiplex primary) request.
5110 ****************************************************************************/
5112 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5115 ssize_t nwritten = -1;
5122 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5123 START_PROFILE(SMBwriteBmpx);
5125 CHECK_FSP(fsp,conn);
5129 tcount = SVAL(inbuf,smb_vwv1);
5130 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5131 write_through = BITSETW(inbuf+smb_vwv7,0);
5132 numtowrite = SVAL(inbuf,smb_vwv10);
5133 smb_doff = SVAL(inbuf,smb_vwv11);
5135 data = smb_base(inbuf) + smb_doff;
5137 /* If this fails we need to send an SMBwriteC response,
5138 not an SMBwritebmpx - set this up now so we don't forget */
5139 SCVAL(outbuf,smb_com,SMBwritec);
5141 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5142 END_PROFILE(SMBwriteBmpx);
5143 return(ERROR_DOS(ERRDOS,ERRlock));
5146 nwritten = write_file(fsp,data,startpos,numtowrite);
5148 if(lp_syncalways(SNUM(conn)) || write_through)
5149 sync_file(conn,fsp);
5151 if(nwritten < (ssize_t)numtowrite) {
5152 END_PROFILE(SMBwriteBmpx);
5153 return(UNIXERROR(ERRHRD,ERRdiskfull));
5156 /* If the maximum to be written to this file
5157 is greater than what we just wrote then set
5158 up a secondary struct to be attached to this
5159 fd, we will use this to cache error messages etc. */
5161 if((ssize_t)tcount > nwritten) {
5162 write_bmpx_struct *wbms;
5163 if(fsp->wbmpx_ptr != NULL)
5164 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5166 wbms = SMB_MALLOC_P(write_bmpx_struct);
5168 DEBUG(0,("Out of memory in reply_readmpx\n"));
5169 END_PROFILE(SMBwriteBmpx);
5170 return(ERROR_DOS(ERRSRV,ERRnoresource));
5172 wbms->wr_mode = write_through;
5173 wbms->wr_discard = False; /* No errors yet */
5174 wbms->wr_total_written = nwritten;
5175 wbms->wr_errclass = 0;
5177 fsp->wbmpx_ptr = wbms;
5180 /* We are returning successfully, set the message type back to
5182 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5184 outsize = set_message(outbuf,1,0,True);
5186 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5188 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5189 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5191 if (write_through && tcount==nwritten) {
5192 /* We need to send both a primary and a secondary response */
5193 smb_setlen(outbuf,outsize - 4);
5194 if (!send_smb(smbd_server_fd(),outbuf))
5195 exit_server("reply_writebmpx: send_smb failed.");
5197 /* Now the secondary */
5198 outsize = set_message(outbuf,1,0,True);
5199 SCVAL(outbuf,smb_com,SMBwritec);
5200 SSVAL(outbuf,smb_vwv0,nwritten);
5203 END_PROFILE(SMBwriteBmpx);
5207 /****************************************************************************
5208 Reply to a SMBwritebs (write block multiplex secondary) request.
5209 ****************************************************************************/
5211 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5214 ssize_t nwritten = -1;
5221 write_bmpx_struct *wbms;
5222 BOOL send_response = False;
5223 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5224 START_PROFILE(SMBwriteBs);
5226 CHECK_FSP(fsp,conn);
5229 tcount = SVAL(inbuf,smb_vwv1);
5230 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5231 numtowrite = SVAL(inbuf,smb_vwv6);
5232 smb_doff = SVAL(inbuf,smb_vwv7);
5234 data = smb_base(inbuf) + smb_doff;
5236 /* We need to send an SMBwriteC response, not an SMBwritebs */
5237 SCVAL(outbuf,smb_com,SMBwritec);
5239 /* This fd should have an auxiliary struct attached,
5240 check that it does */
5241 wbms = fsp->wbmpx_ptr;
5243 END_PROFILE(SMBwriteBs);
5247 /* If write through is set we can return errors, else we must cache them */
5248 write_through = wbms->wr_mode;
5250 /* Check for an earlier error */
5251 if(wbms->wr_discard) {
5252 END_PROFILE(SMBwriteBs);
5253 return -1; /* Just discard the packet */
5256 nwritten = write_file(fsp,data,startpos,numtowrite);
5258 if(lp_syncalways(SNUM(conn)) || write_through)
5259 sync_file(conn,fsp);
5261 if (nwritten < (ssize_t)numtowrite) {
5263 /* We are returning an error - we can delete the aux struct */
5266 fsp->wbmpx_ptr = NULL;
5267 END_PROFILE(SMBwriteBs);
5268 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5270 END_PROFILE(SMBwriteBs);
5271 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5274 /* Increment the total written, if this matches tcount
5275 we can discard the auxiliary struct (hurrah !) and return a writeC */
5276 wbms->wr_total_written += nwritten;
5277 if(wbms->wr_total_written >= tcount) {
5278 if (write_through) {
5279 outsize = set_message(outbuf,1,0,True);
5280 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5281 send_response = True;
5285 fsp->wbmpx_ptr = NULL;
5289 END_PROFILE(SMBwriteBs);
5293 END_PROFILE(SMBwriteBs);
5297 /****************************************************************************
5298 Reply to a SMBgetattrE.
5299 ****************************************************************************/
5301 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5303 SMB_STRUCT_STAT sbuf;
5306 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5307 START_PROFILE(SMBgetattrE);
5309 outsize = set_message(outbuf,11,0,True);
5311 if(!fsp || (fsp->conn != conn)) {
5312 END_PROFILE(SMBgetattrE);
5313 return ERROR_DOS(ERRDOS,ERRbadfid);
5316 /* Do an fstat on this file */
5317 if(fsp_stat(fsp, &sbuf)) {
5318 END_PROFILE(SMBgetattrE);
5319 return(UNIXERROR(ERRDOS,ERRnoaccess));
5322 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5325 * Convert the times into dos times. Set create
5326 * date to be last modify date as UNIX doesn't save
5330 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5331 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5332 /* Should we check pending modtime here ? JRA */
5333 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5336 SIVAL(outbuf,smb_vwv6,0);
5337 SIVAL(outbuf,smb_vwv8,0);
5339 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5340 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5341 SIVAL(outbuf,smb_vwv8,allocation_size);
5343 SSVAL(outbuf,smb_vwv10, mode);
5345 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5347 END_PROFILE(SMBgetattrE);