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 struct current_user current_user;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
43 We're assuming here that '/' is not the second byte in any multibyte char
44 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
46 ****************************************************************************/
48 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
51 const char *s = srcname;
52 NTSTATUS ret = NT_STATUS_OK;
53 BOOL start_of_name_component = True;
54 unsigned int num_bad_components = 0;
57 if (IS_DIRECTORY_SEP(*s)) {
59 * Safe to assume is not the second part of a mb char as this is handled below.
61 /* Eat multiple '/' or '\\' */
62 while (IS_DIRECTORY_SEP(*s)) {
65 if ((d != destname) && (*s != '\0')) {
66 /* We only care about non-leading or trailing '/' or '\\' */
70 start_of_name_component = True;
74 if (start_of_name_component) {
75 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
76 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
79 * No mb char starts with '.' so we're safe checking the directory separator here.
82 /* If we just added a '/' - delete it */
83 if ((d > destname) && (*(d-1) == '/')) {
88 /* Are we at the start ? Can't go back further if so. */
90 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
93 /* Go back one level... */
94 /* We know this is safe as '/' cannot be part of a mb sequence. */
95 /* NOTE - if this assumption is invalid we are not in good shape... */
96 /* Decrement d first as d points to the *next* char to write into. */
97 for (d--; d > destname; d--) {
101 s += 2; /* Else go past the .. */
102 /* We're still at the start of a name component, just the previous one. */
104 if (num_bad_components) {
105 /* Hmmm. Should we only decrement the bad_components if
106 we're removing a bad component ? Need to check this. JRA. */
107 num_bad_components--;
112 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
113 /* Component of pathname can't be "." only. */
114 ret = NT_STATUS_OBJECT_NAME_INVALID;
115 num_bad_components++;
128 return NT_STATUS_OBJECT_NAME_INVALID;
134 switch(next_mb_char_size(s)) {
145 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
147 return NT_STATUS_INVALID_PARAMETER;
150 if (start_of_name_component && num_bad_components) {
151 num_bad_components++;
153 start_of_name_component = False;
156 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
157 if (num_bad_components > 1) {
158 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
166 /****************************************************************************
167 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
168 path or anything including wildcards.
169 We're assuming here that '/' is not the second byte in any multibyte char
170 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
172 ****************************************************************************/
174 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
177 const char *s = srcname;
178 NTSTATUS ret = NT_STATUS_OK;
179 BOOL start_of_name_component = True;
180 unsigned int num_bad_components = 0;
183 if (IS_DIRECTORY_SEP(*s)) {
185 * Safe to assume is not the second part of a mb char as this is handled below.
187 /* Eat multiple '/' or '\\' */
188 while (IS_DIRECTORY_SEP(*s)) {
191 if ((d != destname) && (*s != '\0')) {
192 /* We only care about non-leading or trailing '/' or '\\' */
196 start_of_name_component = True;
200 if (start_of_name_component) {
201 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
202 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
205 * No mb char starts with '.' so we're safe checking the directory separator here.
208 /* If we just added a '/' - delete it */
209 if ((d > destname) && (*(d-1) == '/')) {
214 /* Are we at the start ? Can't go back further if so. */
216 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
219 /* Go back one level... */
220 /* We know this is safe as '/' cannot be part of a mb sequence. */
221 /* NOTE - if this assumption is invalid we are not in good shape... */
222 /* Decrement d first as d points to the *next* char to write into. */
223 for (d--; d > destname; d--) {
227 s += 2; /* Else go past the .. */
228 /* We're still at the start of a name component, just the previous one. */
230 if (num_bad_components) {
231 /* Hmmm. Should we only decrement the bad_components if
232 we're removing a bad component ? Need to check this. JRA. */
233 num_bad_components--;
238 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
239 /* Component of pathname can't be "." only. */
240 ret = NT_STATUS_OBJECT_NAME_INVALID;
241 num_bad_components++;
250 switch(next_mb_char_size(s)) {
261 DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
263 return NT_STATUS_INVALID_PARAMETER;
266 if (start_of_name_component && num_bad_components) {
267 num_bad_components++;
269 start_of_name_component = False;
272 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
273 /* For some strange reason being called from findfirst changes
274 the num_components number to cause the error return to change. JRA. */
275 if (num_bad_components > 2) {
276 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
284 /****************************************************************************
285 Pull a string and check the path - provide for error return.
286 ****************************************************************************/
288 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)
291 char *tmppath_ptr = tmppath;
294 SMB_ASSERT(dest_len == sizeof(pstring));
298 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
300 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
302 if (allow_wcard_names) {
303 *err = check_path_syntax_wcard(dest, tmppath);
305 *err = check_path_syntax(dest, tmppath);
310 /****************************************************************************
311 Reply to a special message.
312 ****************************************************************************/
314 int reply_special(char *inbuf,char *outbuf)
317 int msg_type = CVAL(inbuf,0);
318 int msg_flags = CVAL(inbuf,1);
322 static BOOL already_got_session = False;
326 memset(outbuf,'\0',smb_size);
328 smb_setlen(outbuf,0);
331 case 0x81: /* session request */
333 if (already_got_session) {
334 exit_server("multiple session request not permitted");
337 SCVAL(outbuf,0,0x82);
339 if (name_len(inbuf+4) > 50 ||
340 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
341 DEBUG(0,("Invalid name length in session request\n"));
344 name_extract(inbuf,4,name1);
345 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
346 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
349 set_local_machine_name(name1, True);
350 set_remote_machine_name(name2, True);
352 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
353 get_local_machine_name(), get_remote_machine_name(),
356 if (name_type == 'R') {
357 /* We are being asked for a pathworks session ---
359 SCVAL(outbuf, 0,0x83);
363 /* only add the client's machine name to the list
364 of possibly valid usernames if we are operating
365 in share mode security */
366 if (lp_security() == SEC_SHARE) {
367 add_session_user(get_remote_machine_name());
370 reload_services(True);
373 already_got_session = True;
376 case 0x89: /* session keepalive request
377 (some old clients produce this?) */
378 SCVAL(outbuf,0,SMBkeepalive);
382 case 0x82: /* positive session response */
383 case 0x83: /* negative session response */
384 case 0x84: /* retarget session response */
385 DEBUG(0,("Unexpected session response\n"));
388 case SMBkeepalive: /* session keepalive */
393 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
394 msg_type, msg_flags));
399 /****************************************************************************
401 ****************************************************************************/
403 int reply_tcon(connection_struct *conn,
404 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
411 uint16 vuid = SVAL(inbuf,smb_uid);
415 DATA_BLOB password_blob;
417 START_PROFILE(SMBtcon);
419 *service_buf = *password = *dev = 0;
421 p = smb_buf(inbuf)+1;
422 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
423 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
425 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
427 p = strrchr_m(service_buf,'\\');
431 service = service_buf;
434 password_blob = data_blob(password, pwlen+1);
436 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
438 data_blob_clear_free(&password_blob);
441 END_PROFILE(SMBtcon);
442 return ERROR_NT(nt_status);
445 outsize = set_message(outbuf,2,0,True);
446 SSVAL(outbuf,smb_vwv0,max_recv);
447 SSVAL(outbuf,smb_vwv1,conn->cnum);
448 SSVAL(outbuf,smb_tid,conn->cnum);
450 DEBUG(3,("tcon service=%s cnum=%d\n",
451 service, conn->cnum));
453 END_PROFILE(SMBtcon);
457 /****************************************************************************
458 Reply to a tcon and X.
459 ****************************************************************************/
461 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
466 /* what the cleint thinks the device is */
467 fstring client_devicetype;
468 /* what the server tells the client the share represents */
469 const char *server_devicetype;
471 uint16 vuid = SVAL(inbuf,smb_uid);
472 int passlen = SVAL(inbuf,smb_vwv3);
476 START_PROFILE(SMBtconX);
478 *service = *client_devicetype = 0;
480 /* we might have to close an old one */
481 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
482 close_cnum(conn,vuid);
485 if (passlen > MAX_PASS_LEN) {
486 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
489 if (global_encrypted_passwords_negotiated) {
490 password = data_blob(smb_buf(inbuf),passlen);
492 password = data_blob(smb_buf(inbuf),passlen+1);
493 /* Ensure correct termination */
494 password.data[passlen]=0;
497 p = smb_buf(inbuf) + passlen;
498 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
501 * the service name can be either: \\server\share
502 * or share directly like on the DELL PowerVault 705
505 q = strchr_m(path+2,'\\');
507 END_PROFILE(SMBtconX);
508 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
510 fstrcpy(service,q+1);
513 fstrcpy(service,path);
515 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
517 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
519 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
521 data_blob_clear_free(&password);
524 END_PROFILE(SMBtconX);
525 return ERROR_NT(nt_status);
529 server_devicetype = "IPC";
530 else if ( IS_PRINT(conn) )
531 server_devicetype = "LPT1:";
533 server_devicetype = "A:";
535 if (Protocol < PROTOCOL_NT1) {
536 set_message(outbuf,2,0,True);
538 p += srvstr_push(outbuf, p, server_devicetype, -1,
539 STR_TERMINATE|STR_ASCII);
540 set_message_end(outbuf,p);
542 /* NT sets the fstype of IPC$ to the null string */
543 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
545 set_message(outbuf,3,0,True);
548 p += srvstr_push(outbuf, p, server_devicetype, -1,
549 STR_TERMINATE|STR_ASCII);
550 p += srvstr_push(outbuf, p, fstype, -1,
553 set_message_end(outbuf,p);
555 /* what does setting this bit do? It is set by NT4 and
556 may affect the ability to autorun mounted cdroms */
557 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
558 (lp_csc_policy(SNUM(conn)) << 2));
560 init_dfsroot(conn, inbuf, outbuf);
564 DEBUG(3,("tconX service=%s \n",
567 /* set the incoming and outgoing tid to the just created one */
568 SSVAL(inbuf,smb_tid,conn->cnum);
569 SSVAL(outbuf,smb_tid,conn->cnum);
571 END_PROFILE(SMBtconX);
572 return chain_reply(inbuf,outbuf,length,bufsize);
575 /****************************************************************************
576 Reply to an unknown type.
577 ****************************************************************************/
579 int reply_unknown(char *inbuf,char *outbuf)
582 type = CVAL(inbuf,smb_com);
584 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
585 smb_fn_name(type), type, type));
587 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
590 /****************************************************************************
592 ****************************************************************************/
594 int reply_ioctl(connection_struct *conn,
595 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
597 uint16 device = SVAL(inbuf,smb_vwv1);
598 uint16 function = SVAL(inbuf,smb_vwv2);
599 uint32 ioctl_code = (device << 16) + function;
600 int replysize, outsize;
602 START_PROFILE(SMBioctl);
604 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
606 switch (ioctl_code) {
607 case IOCTL_QUERY_JOB_INFO:
611 END_PROFILE(SMBioctl);
612 return(ERROR_DOS(ERRSRV,ERRnosupport));
615 outsize = set_message(outbuf,8,replysize+1,True);
616 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
617 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
618 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
619 p = smb_buf(outbuf) + 1; /* Allow for alignment */
621 switch (ioctl_code) {
622 case IOCTL_QUERY_JOB_INFO:
624 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
626 END_PROFILE(SMBioctl);
627 return(UNIXERROR(ERRDOS,ERRbadfid));
629 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
630 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
632 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
638 END_PROFILE(SMBioctl);
642 /****************************************************************************
644 ****************************************************************************/
646 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
651 BOOL bad_path = False;
652 SMB_STRUCT_STAT sbuf;
655 START_PROFILE(SMBchkpth);
657 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
658 if (!NT_STATUS_IS_OK(status)) {
659 END_PROFILE(SMBchkpth);
660 return ERROR_NT(status);
663 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
665 unix_convert(name,conn,0,&bad_path,&sbuf);
667 END_PROFILE(SMBchkpth);
668 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
671 if (check_name(name,conn)) {
672 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
673 if (!(ok = S_ISDIR(sbuf.st_mode))) {
674 END_PROFILE(SMBchkpth);
675 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
680 /* We special case this - as when a Windows machine
681 is parsing a path is steps through the components
682 one at a time - if a component fails it expects
683 ERRbadpath, not ERRbadfile.
685 if(errno == ENOENT) {
687 * Windows returns different error codes if
688 * the parent directory is valid but not the
689 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
690 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
691 * if the path is invalid. This is different from set_bad_path_error()
692 * in the non-NT error case.
694 END_PROFILE(SMBchkpth);
695 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
698 END_PROFILE(SMBchkpth);
699 return(UNIXERROR(ERRDOS,ERRbadpath));
702 outsize = set_message(outbuf,0,0,True);
703 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
705 END_PROFILE(SMBchkpth);
709 /****************************************************************************
711 ****************************************************************************/
713 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
717 SMB_STRUCT_STAT sbuf;
722 BOOL bad_path = False;
726 START_PROFILE(SMBgetatr);
728 p = smb_buf(inbuf) + 1;
729 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
730 if (!NT_STATUS_IS_OK(status)) {
731 END_PROFILE(SMBgetatr);
732 return ERROR_NT(status);
735 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
737 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
738 under WfWg - weird! */
740 mode = aHIDDEN | aDIR;
741 if (!CAN_WRITE(conn))
747 unix_convert(fname,conn,0,&bad_path,&sbuf);
749 END_PROFILE(SMBgetatr);
750 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
752 if (check_name(fname,conn)) {
753 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
754 mode = dos_mode(conn,fname,&sbuf);
756 mtime = sbuf.st_mtime;
761 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
767 END_PROFILE(SMBgetatr);
768 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
771 outsize = set_message(outbuf,10,0,True);
773 SSVAL(outbuf,smb_vwv0,mode);
774 if(lp_dos_filetime_resolution(SNUM(conn)) )
775 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
777 put_dos_date3(outbuf,smb_vwv1,mtime);
778 SIVAL(outbuf,smb_vwv3,(uint32)size);
780 if (Protocol >= PROTOCOL_NT1)
781 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
783 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
785 END_PROFILE(SMBgetatr);
789 /****************************************************************************
791 ****************************************************************************/
793 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
800 SMB_STRUCT_STAT sbuf;
801 BOOL bad_path = False;
805 START_PROFILE(SMBsetatr);
807 p = smb_buf(inbuf) + 1;
808 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
809 if (!NT_STATUS_IS_OK(status)) {
810 END_PROFILE(SMBsetatr);
811 return ERROR_NT(status);
814 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
816 unix_convert(fname,conn,0,&bad_path,&sbuf);
818 END_PROFILE(SMBsetatr);
819 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
822 mode = SVAL(inbuf,smb_vwv0);
823 mtime = make_unix_date3(inbuf+smb_vwv1);
825 if (mode != FILE_ATTRIBUTE_NORMAL) {
826 if (VALID_STAT_OF_DIR(sbuf))
831 if (check_name(fname,conn)) {
832 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
839 ok = set_filetime(conn,fname,mtime);
842 END_PROFILE(SMBsetatr);
843 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
846 outsize = set_message(outbuf,0,0,True);
848 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
850 END_PROFILE(SMBsetatr);
854 /****************************************************************************
856 ****************************************************************************/
858 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
861 SMB_BIG_UINT dfree,dsize,bsize;
862 START_PROFILE(SMBdskattr);
864 if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
865 END_PROFILE(SMBdskattr);
866 return(UNIXERROR(ERRHRD,ERRgeneral));
869 outsize = set_message(outbuf,5,0,True);
871 if (Protocol <= PROTOCOL_LANMAN2) {
872 double total_space, free_space;
873 /* we need to scale this to a number that DOS6 can handle. We
874 use floating point so we can handle large drives on systems
875 that don't have 64 bit integers
877 we end up displaying a maximum of 2G to DOS systems
879 total_space = dsize * (double)bsize;
880 free_space = dfree * (double)bsize;
882 dsize = (total_space+63*512) / (64*512);
883 dfree = (free_space+63*512) / (64*512);
885 if (dsize > 0xFFFF) dsize = 0xFFFF;
886 if (dfree > 0xFFFF) dfree = 0xFFFF;
888 SSVAL(outbuf,smb_vwv0,dsize);
889 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
890 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
891 SSVAL(outbuf,smb_vwv3,dfree);
893 SSVAL(outbuf,smb_vwv0,dsize);
894 SSVAL(outbuf,smb_vwv1,bsize/512);
895 SSVAL(outbuf,smb_vwv2,512);
896 SSVAL(outbuf,smb_vwv3,dfree);
899 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
901 END_PROFILE(SMBdskattr);
905 /****************************************************************************
907 Can be called from SMBsearch, SMBffirst or SMBfunique.
908 ****************************************************************************/
910 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
920 unsigned int numentries = 0;
921 unsigned int maxentries = 0;
922 BOOL finished = False;
929 BOOL check_descend = False;
930 BOOL expect_close = False;
931 BOOL can_open = True;
932 BOOL bad_path = False;
934 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
936 START_PROFILE(SMBsearch);
938 *mask = *directory = *fname = 0;
940 /* If we were called as SMBffirst then we must expect close. */
941 if(CVAL(inbuf,smb_com) == SMBffirst)
944 outsize = set_message(outbuf,1,3,True);
945 maxentries = SVAL(inbuf,smb_vwv0);
946 dirtype = SVAL(inbuf,smb_vwv1);
947 p = smb_buf(inbuf) + 1;
948 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
949 if (!NT_STATUS_IS_OK(nt_status)) {
950 END_PROFILE(SMBsearch);
951 return ERROR_NT(nt_status);
954 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
957 status_len = SVAL(p, 0);
960 /* dirtype &= ~aDIR; */
962 if (status_len == 0) {
963 SMB_STRUCT_STAT sbuf;
966 pstrcpy(directory,path);
968 unix_convert(directory,conn,0,&bad_path,&sbuf);
971 if (!check_name(directory,conn))
974 p = strrchr_m(dir2,'/');
983 p = strrchr_m(directory,'/');
989 if (strlen(directory) == 0)
990 pstrcpy(directory,".");
991 memset((char *)status,'\0',21);
992 SCVAL(status,0,(dirtype & 0x1F));
997 status_dirtype = CVAL(status,0) & 0x1F;
998 if (status_dirtype != (dirtype & 0x1F))
999 dirtype = status_dirtype;
1001 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1004 string_set(&conn->dirpath,dptr_path(dptr_num));
1005 pstrcpy(mask, dptr_wcard(dptr_num));
1009 p = smb_buf(outbuf) + 3;
1012 if (status_len == 0) {
1013 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1015 if(dptr_num == -2) {
1016 END_PROFILE(SMBsearch);
1017 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1019 END_PROFILE(SMBsearch);
1020 return ERROR_DOS(ERRDOS,ERRnofids);
1022 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1023 END_PROFILE(SMBsearch);
1024 return ERROR_DOS(ERRDOS,ERRnomem);
1027 dirtype = dptr_attr(dptr_num);
1030 DEBUG(4,("dptr_num is %d\n",dptr_num));
1033 if ((dirtype&0x1F) == aVOLID) {
1034 memcpy(p,status,21);
1035 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1036 0,aVOLID,0,!allow_long_path_components);
1037 dptr_fill(p+12,dptr_num);
1038 if (dptr_zero(p+12) && (status_len==0))
1042 p += DIR_STRUCT_SIZE;
1045 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1047 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1048 conn->dirpath,lp_dontdescend(SNUM(conn))));
1049 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1050 check_descend = True;
1052 for (i=numentries;(i<maxentries) && !finished;i++) {
1053 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1055 memcpy(p,status,21);
1056 make_dir_struct(p,mask,fname,size, mode,date,
1057 !allow_long_path_components);
1058 dptr_fill(p+12,dptr_num);
1060 p += DIR_STRUCT_SIZE;
1070 /* If we were called as SMBffirst with smb_search_id == NULL
1071 and no entries were found then return error and close dirptr
1074 if (numentries == 0 || !ok) {
1075 dptr_close(&dptr_num);
1076 } else if(ok && expect_close && status_len == 0) {
1077 /* Close the dptr - we know it's gone */
1078 dptr_close(&dptr_num);
1081 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1082 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1083 dptr_close(&dptr_num);
1086 if ((numentries == 0) && !ms_has_wild(mask)) {
1087 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1090 SSVAL(outbuf,smb_vwv0,numentries);
1091 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1092 SCVAL(smb_buf(outbuf),0,5);
1093 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1095 /* The replies here are never long name. */
1096 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1097 if (!allow_long_path_components) {
1098 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1101 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1102 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1104 outsize += DIR_STRUCT_SIZE*numentries;
1105 smb_setlen(outbuf,outsize - 4);
1107 if ((! *directory) && dptr_path(dptr_num))
1108 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1110 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1111 smb_fn_name(CVAL(inbuf,smb_com)),
1112 mask, directory, dirtype, numentries, maxentries ) );
1114 END_PROFILE(SMBsearch);
1118 /****************************************************************************
1119 Reply to a fclose (stop directory search).
1120 ****************************************************************************/
1122 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1132 START_PROFILE(SMBfclose);
1134 outsize = set_message(outbuf,1,0,True);
1135 p = smb_buf(inbuf) + 1;
1136 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1137 if (!NT_STATUS_IS_OK(err)) {
1138 END_PROFILE(SMBfclose);
1139 return ERROR_NT(err);
1142 status_len = SVAL(p,0);
1145 if (status_len == 0) {
1146 END_PROFILE(SMBfclose);
1147 return ERROR_DOS(ERRSRV,ERRsrverror);
1150 memcpy(status,p,21);
1152 if(dptr_fetch(status+12,&dptr_num)) {
1153 /* Close the dptr - we know it's gone */
1154 dptr_close(&dptr_num);
1157 SSVAL(outbuf,smb_vwv0,0);
1159 DEBUG(3,("search close\n"));
1161 END_PROFILE(SMBfclose);
1165 /****************************************************************************
1167 ****************************************************************************/
1169 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1178 SMB_STRUCT_STAT sbuf;
1179 BOOL bad_path = False;
1181 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1182 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1184 START_PROFILE(SMBopen);
1186 share_mode = SVAL(inbuf,smb_vwv0);
1188 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 END_PROFILE(SMBopen);
1191 return ERROR_NT(status);
1194 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1196 unix_convert(fname,conn,0,&bad_path,&sbuf);
1198 END_PROFILE(SMBopen);
1199 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1202 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1203 (uint32)dos_attr, oplock_request,&rmode,NULL);
1206 END_PROFILE(SMBopen);
1207 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1208 /* We have re-scheduled this call. */
1211 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1214 size = sbuf.st_size;
1215 fmode = dos_mode(conn,fname,&sbuf);
1216 mtime = sbuf.st_mtime;
1219 DEBUG(3,("attempt to open a directory %s\n",fname));
1220 close_file(fsp,False);
1221 END_PROFILE(SMBopen);
1222 return ERROR_DOS(ERRDOS,ERRnoaccess);
1225 outsize = set_message(outbuf,7,0,True);
1226 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1227 SSVAL(outbuf,smb_vwv1,fmode);
1228 if(lp_dos_filetime_resolution(SNUM(conn)) )
1229 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1231 put_dos_date3(outbuf,smb_vwv2,mtime);
1232 SIVAL(outbuf,smb_vwv4,(uint32)size);
1233 SSVAL(outbuf,smb_vwv6,rmode);
1235 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1236 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1238 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1239 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1240 END_PROFILE(SMBopen);
1244 /****************************************************************************
1245 Reply to an open and X.
1246 ****************************************************************************/
1248 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1251 int smb_mode = SVAL(inbuf,smb_vwv3);
1252 int smb_attr = SVAL(inbuf,smb_vwv5);
1253 /* Breakout the oplock request bits so we can set the
1254 reply bits separately. */
1255 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1256 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1257 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1259 int open_flags = SVAL(inbuf,smb_vwv2);
1260 int smb_sattr = SVAL(inbuf,smb_vwv4);
1261 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1263 int smb_ofun = SVAL(inbuf,smb_vwv8);
1265 int fmode=0,mtime=0,rmode=0;
1266 SMB_STRUCT_STAT sbuf;
1268 BOOL bad_path = False;
1271 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1272 ssize_t retval = -1;
1274 START_PROFILE(SMBopenX);
1276 /* If it's an IPC, pass off the pipe handler. */
1278 if (lp_nt_pipe_support()) {
1279 END_PROFILE(SMBopenX);
1280 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1282 END_PROFILE(SMBopenX);
1283 return ERROR_DOS(ERRSRV,ERRaccess);
1287 /* XXXX we need to handle passed times, sattr and flags */
1288 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 END_PROFILE(SMBopenX);
1291 return ERROR_NT(status);
1294 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1296 unix_convert(fname,conn,0,&bad_path,&sbuf);
1298 END_PROFILE(SMBopenX);
1299 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1302 /* Strange open mode mapping. */
1303 if (smb_ofun == 0) {
1304 if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) {
1305 smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
1307 END_PROFILE(SMBopenX);
1308 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1312 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1313 oplock_request, &rmode,&smb_action);
1316 END_PROFILE(SMBopenX);
1317 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1318 /* We have re-scheduled this call. */
1321 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1324 size = sbuf.st_size;
1326 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1327 if the file is truncated or created. */
1328 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1329 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1330 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1331 close_file(fsp,False);
1332 END_PROFILE(SMBntcreateX);
1333 return ERROR_NT(NT_STATUS_DISK_FULL);
1335 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1337 close_file(fsp,False);
1338 END_PROFILE(SMBwrite);
1339 return ERROR_NT(NT_STATUS_DISK_FULL);
1341 size = get_allocation_size(conn,fsp,&sbuf);
1344 fmode = dos_mode(conn,fname,&sbuf);
1345 mtime = sbuf.st_mtime;
1347 close_file(fsp,False);
1348 END_PROFILE(SMBopenX);
1349 return ERROR_DOS(ERRDOS,ERRnoaccess);
1352 /* If the caller set the extended oplock request bit
1353 and we granted one (by whatever means) - set the
1354 correct bit for extended oplock reply.
1357 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1358 smb_action |= EXTENDED_OPLOCK_GRANTED;
1360 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1361 smb_action |= EXTENDED_OPLOCK_GRANTED;
1363 /* If the caller set the core oplock request bit
1364 and we granted one (by whatever means) - set the
1365 correct bit for core oplock reply.
1368 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1369 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1371 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1372 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1374 set_message(outbuf,15,0,True);
1375 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1376 SSVAL(outbuf,smb_vwv3,fmode);
1377 if(lp_dos_filetime_resolution(SNUM(conn)) )
1378 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1380 put_dos_date3(outbuf,smb_vwv4,mtime);
1381 SIVAL(outbuf,smb_vwv6,(uint32)size);
1382 SSVAL(outbuf,smb_vwv8,rmode);
1383 SSVAL(outbuf,smb_vwv11,smb_action);
1385 END_PROFILE(SMBopenX);
1386 return chain_reply(inbuf,outbuf,length,bufsize);
1389 /****************************************************************************
1390 Reply to a SMBulogoffX.
1391 ****************************************************************************/
1393 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1395 uint16 vuid = SVAL(inbuf,smb_uid);
1396 user_struct *vuser = get_valid_user_struct(vuid);
1397 START_PROFILE(SMBulogoffX);
1400 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1402 /* in user level security we are supposed to close any files
1403 open by this user */
1404 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1405 file_close_user(vuid);
1407 invalidate_vuid(vuid);
1409 set_message(outbuf,2,0,True);
1411 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1413 END_PROFILE(SMBulogoffX);
1414 return chain_reply(inbuf,outbuf,length,bufsize);
1417 /****************************************************************************
1418 Reply to a mknew or a create.
1419 ****************************************************************************/
1421 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1428 BOOL bad_path = False;
1430 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1431 SMB_STRUCT_STAT sbuf;
1433 START_PROFILE(SMBcreate);
1435 com = SVAL(inbuf,smb_com);
1437 createmode = SVAL(inbuf,smb_vwv0);
1438 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 END_PROFILE(SMBcreate);
1441 return ERROR_NT(status);
1444 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1446 unix_convert(fname,conn,0,&bad_path,&sbuf);
1448 END_PROFILE(SMBcreate);
1449 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1452 if (createmode & aVOLID)
1453 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1455 if(com == SMBmknew) {
1456 /* We should fail if file exists. */
1457 ofun = FILE_CREATE_IF_NOT_EXIST;
1459 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1460 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1463 /* Open file in dos compatibility share mode. */
1464 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1465 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1468 END_PROFILE(SMBcreate);
1469 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1470 /* We have re-scheduled this call. */
1473 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1476 outsize = set_message(outbuf,1,0,True);
1477 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1479 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1480 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1482 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1483 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1485 DEBUG( 2, ( "new file %s\n", fname ) );
1486 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1488 END_PROFILE(SMBcreate);
1492 /****************************************************************************
1493 Reply to a create temporary file.
1494 ****************************************************************************/
1496 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1501 BOOL bad_path = False;
1503 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1505 SMB_STRUCT_STAT sbuf;
1508 unsigned int namelen;
1510 START_PROFILE(SMBctemp);
1512 createattr = SVAL(inbuf,smb_vwv0);
1513 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 END_PROFILE(SMBctemp);
1516 return ERROR_NT(status);
1519 pstrcat(fname,"/TMXXXXXX");
1521 pstrcat(fname,"TMXXXXXX");
1524 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1526 unix_convert(fname,conn,0,&bad_path,&sbuf);
1528 END_PROFILE(SMBctemp);
1529 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1532 tmpfd = smb_mkstemp(fname);
1534 END_PROFILE(SMBctemp);
1535 return(UNIXERROR(ERRDOS,ERRnoaccess));
1538 SMB_VFS_STAT(conn,fname,&sbuf);
1540 /* Open file in dos compatibility share mode. */
1541 /* We should fail if file does not exist. */
1542 fsp = open_file_shared(conn,fname,&sbuf,
1543 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1544 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1545 (uint32)createattr, oplock_request, NULL, NULL);
1547 /* close fd from smb_mkstemp() */
1551 END_PROFILE(SMBctemp);
1552 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1553 /* We have re-scheduled this call. */
1556 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1559 outsize = set_message(outbuf,1,0,True);
1560 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1562 /* the returned filename is relative to the directory */
1563 s = strrchr_m(fname, '/');
1569 p = smb_buf(outbuf);
1571 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1572 thing in the byte section. JRA */
1573 SSVALS(p, 0, -1); /* what is this? not in spec */
1575 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1577 outsize = set_message_end(outbuf, p);
1579 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1580 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1582 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1583 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1585 DEBUG( 2, ( "created temp file %s\n", fname ) );
1586 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1587 fname, fsp->fd, sbuf.st_mode ) );
1589 END_PROFILE(SMBctemp);
1593 /*******************************************************************
1594 Check if a user is allowed to rename a file.
1595 ********************************************************************/
1597 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1604 if (!CAN_WRITE(conn))
1605 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1607 fmode = dos_mode(conn,fname,pst);
1608 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1609 return NT_STATUS_NO_SUCH_FILE;
1611 if (S_ISDIR(pst->st_mode))
1612 return NT_STATUS_OK;
1614 /* We need a better way to return NT status codes from open... */
1615 set_saved_error_triple(0, 0, NT_STATUS_OK);
1617 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1618 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1622 if (get_saved_error_triple(NULL, NULL, &ret)) {
1623 set_saved_error_triple(0, 0, NT_STATUS_OK);
1626 set_saved_error_triple(0, 0, NT_STATUS_OK);
1627 return NT_STATUS_ACCESS_DENIED;
1629 close_file(fsp,False);
1630 return NT_STATUS_OK;
1633 /*******************************************************************
1634 Check if a user is allowed to delete a file.
1635 ********************************************************************/
1637 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1639 SMB_STRUCT_STAT sbuf;
1645 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1648 if (!CAN_WRITE(conn))
1649 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1651 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1652 if(errno == ENOENT) {
1654 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1656 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1658 return map_nt_error_from_unix(errno);
1661 fmode = dos_mode(conn,fname,&sbuf);
1663 /* Can't delete a directory. */
1665 return NT_STATUS_FILE_IS_A_DIRECTORY;
1667 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1668 return NT_STATUS_OBJECT_NAME_INVALID;
1669 #endif /* JRATEST */
1671 if (!lp_delete_readonly(SNUM(conn))) {
1673 return NT_STATUS_CANNOT_DELETE;
1675 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1676 return NT_STATUS_NO_SUCH_FILE;
1678 if (check_is_at_open) {
1679 if (!can_delete_file_in_directory(conn, fname)) {
1680 return NT_STATUS_ACCESS_DENIED;
1683 /* On open checks the open itself will check the share mode, so
1684 don't do it here as we'll get it wrong. */
1686 /* We need a better way to return NT status codes from open... */
1687 set_saved_error_triple(0, 0, NT_STATUS_OK);
1689 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1690 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1694 if (get_saved_error_triple(NULL, NULL, &ret)) {
1695 set_saved_error_triple(0, 0, NT_STATUS_OK);
1698 set_saved_error_triple(0, 0, NT_STATUS_OK);
1699 return NT_STATUS_ACCESS_DENIED;
1701 close_file(fsp,False);
1703 return NT_STATUS_OK;
1706 /****************************************************************************
1707 The guts of the unlink command, split out so it may be called by the NT SMB
1709 ****************************************************************************/
1711 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1717 NTSTATUS error = NT_STATUS_OK;
1719 BOOL bad_path = False;
1721 SMB_STRUCT_STAT sbuf;
1723 *directory = *mask = 0;
1725 /* We must check for wildcards in the name given
1726 * directly by the client - before any unmangling.
1727 * This prevents an unmangling of a UNIX name containing
1728 * a DOS wildcard like '*' or '?' from unmangling into
1729 * a wildcard delete which was not intended.
1730 * FIX for #226. JRA.
1733 has_wild = ms_has_wild(name);
1735 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1737 p = strrchr_m(name,'/');
1739 pstrcpy(directory,".");
1743 pstrcpy(directory,name);
1748 * We should only check the mangled cache
1749 * here if unix_convert failed. This means
1750 * that the path in 'mask' doesn't exist
1751 * on the file system and so we need to look
1752 * for a possible mangle. This patch from
1753 * Tine Smukavec <valentin.smukavec@hermes.si>.
1756 if (!rc && mangle_is_mangled(mask))
1757 mangle_check_cache( mask, sizeof(pstring)-1 );
1760 pstrcat(directory,"/");
1761 pstrcat(directory,mask);
1762 error = can_delete(conn,directory,dirtype,bad_path,False);
1763 if (!NT_STATUS_IS_OK(error))
1766 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1770 struct smb_Dir *dir_hnd = NULL;
1773 if (check_name(directory,conn))
1774 dir_hnd = OpenDir(conn, directory);
1776 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1777 the pattern matches against the long name, otherwise the short name
1778 We don't implement this yet XXXX
1783 error = NT_STATUS_NO_SUCH_FILE;
1785 if (strequal(mask,"????????.???"))
1788 while ((dname = ReadDirName(dir_hnd, &offset))) {
1791 BOOL sys_direntry = False;
1792 pstrcpy(fname,dname);
1794 if (!is_visible_file(conn, directory, dname, &st, True)) {
1798 /* Quick check for "." and ".." */
1799 if (fname[0] == '.') {
1800 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1801 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1802 sys_direntry = True;
1809 if(!mask_match(fname, mask, conn->case_sensitive))
1813 error = NT_STATUS_OBJECT_NAME_INVALID;
1814 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1819 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1820 error = can_delete(conn,fname,dirtype,bad_path,False);
1821 if (!NT_STATUS_IS_OK(error)) {
1824 if (SMB_VFS_UNLINK(conn,fname) == 0)
1826 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1832 if (count == 0 && NT_STATUS_IS_OK(error)) {
1833 error = map_nt_error_from_unix(errno);
1839 /****************************************************************************
1841 ****************************************************************************/
1843 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1850 START_PROFILE(SMBunlink);
1852 dirtype = SVAL(inbuf,smb_vwv0);
1854 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 END_PROFILE(SMBunlink);
1857 return ERROR_NT(status);
1860 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1862 DEBUG(3,("reply_unlink : %s\n",name));
1864 status = unlink_internals(conn, dirtype, name);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1867 /* We have re-scheduled this call. */
1870 return ERROR_NT(status);
1874 * Win2k needs a changenotify request response before it will
1875 * update after a rename..
1877 process_pending_change_notify_queue((time_t)0);
1879 outsize = set_message(outbuf,0,0,True);
1881 END_PROFILE(SMBunlink);
1885 /****************************************************************************
1887 ****************************************************************************/
1889 static void fail_readraw(void)
1892 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1894 exit_server(errstr);
1897 #if defined(WITH_SENDFILE)
1898 /****************************************************************************
1899 Fake (read/write) sendfile. Returns -1 on read or write fail.
1900 ****************************************************************************/
1902 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1906 /* Paranioa check... */
1907 if (nread > bufsize) {
1912 ret = read_file(fsp,buf,startpos,nread);
1918 /* If we had a short read, fill with zeros. */
1920 memset(buf, '\0', nread - ret);
1923 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1927 return (ssize_t)nread;
1931 /****************************************************************************
1932 Use sendfile in readbraw.
1933 ****************************************************************************/
1935 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1936 ssize_t mincount, char *outbuf, int out_buffsize)
1940 #if defined(WITH_SENDFILE)
1942 * We can only use sendfile on a non-chained packet
1943 * but we can use on a non-oplocked file. tridge proved this
1944 * on a train in Germany :-). JRA.
1945 * reply_readbraw has already checked the length.
1948 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1951 _smb_setlen(outbuf,nread);
1952 header.data = outbuf;
1956 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1957 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1958 if (errno == ENOSYS) {
1959 goto normal_readbraw;
1963 * Special hack for broken Linux with no working sendfile. If we
1964 * return EINTR we sent the header but not the rest of the data.
1965 * Fake this up by doing read/write calls.
1967 if (errno == EINTR) {
1968 /* Ensure we don't do this again. */
1969 set_use_sendfile(SNUM(conn), False);
1970 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1972 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1973 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1974 fsp->fsp_name, strerror(errno) ));
1975 exit_server("send_file_readbraw fake_sendfile failed");
1980 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1981 fsp->fsp_name, strerror(errno) ));
1982 exit_server("send_file_readbraw sendfile failed");
1992 ret = read_file(fsp,outbuf+4,startpos,nread);
1993 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2002 _smb_setlen(outbuf,ret);
2003 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2007 /****************************************************************************
2008 Reply to a readbraw (core+ protocol).
2009 ****************************************************************************/
2011 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2013 ssize_t maxcount,mincount;
2016 char *header = outbuf;
2018 START_PROFILE(SMBreadbraw);
2020 if (srv_is_signing_active()) {
2021 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2025 * Special check if an oplock break has been issued
2026 * and the readraw request croses on the wire, we must
2027 * return a zero length response here.
2030 if(global_oplock_break) {
2031 _smb_setlen(header,0);
2032 if (write_data(smbd_server_fd(),header,4) != 4)
2034 DEBUG(5,("readbraw - oplock break finished\n"));
2035 END_PROFILE(SMBreadbraw);
2039 fsp = file_fsp(inbuf,smb_vwv0);
2041 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2043 * fsp could be NULL here so use the value from the packet. JRA.
2045 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2046 _smb_setlen(header,0);
2047 if (write_data(smbd_server_fd(),header,4) != 4)
2049 END_PROFILE(SMBreadbraw);
2053 CHECK_FSP(fsp,conn);
2055 flush_write_cache(fsp, READRAW_FLUSH);
2057 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2058 if(CVAL(inbuf,smb_wct) == 10) {
2060 * This is a large offset (64 bit) read.
2062 #ifdef LARGE_SMB_OFF_T
2064 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2066 #else /* !LARGE_SMB_OFF_T */
2069 * Ensure we haven't been sent a >32 bit offset.
2072 if(IVAL(inbuf,smb_vwv8) != 0) {
2073 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2074 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2075 _smb_setlen(header,0);
2076 if (write_data(smbd_server_fd(),header,4) != 4)
2078 END_PROFILE(SMBreadbraw);
2082 #endif /* LARGE_SMB_OFF_T */
2085 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2086 _smb_setlen(header,0);
2087 if (write_data(smbd_server_fd(),header,4) != 4)
2089 END_PROFILE(SMBreadbraw);
2093 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2094 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2096 /* ensure we don't overrun the packet size */
2097 maxcount = MIN(65535,maxcount);
2099 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2100 SMB_OFF_T size = fsp->size;
2101 SMB_OFF_T sizeneeded = startpos + maxcount;
2103 if (size < sizeneeded) {
2105 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
2107 if (!fsp->can_write)
2111 if (startpos >= size)
2114 nread = MIN(maxcount,(size - startpos));
2117 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2118 if (nread < mincount)
2122 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2123 (int)maxcount, (int)mincount, (int)nread ) );
2125 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2127 DEBUG(5,("readbraw finished\n"));
2128 END_PROFILE(SMBreadbraw);
2133 #define DBGC_CLASS DBGC_LOCKING
2135 /****************************************************************************
2136 Reply to a lockread (core+ protocol).
2137 ****************************************************************************/
2139 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2147 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2148 BOOL my_lock_ctx = False;
2149 START_PROFILE(SMBlockread);
2151 CHECK_FSP(fsp,conn);
2154 release_level_2_oplocks_on_change(fsp);
2156 numtoread = SVAL(inbuf,smb_vwv1);
2157 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2159 outsize = set_message(outbuf,5,3,True);
2160 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2161 data = smb_buf(outbuf) + 3;
2164 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2165 * protocol request that predates the read/write lock concept.
2166 * Thus instead of asking for a read lock here we need to ask
2167 * for a write lock. JRA.
2168 * Note that the requested lock size is unaffected by max_recv.
2171 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2172 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2174 if (NT_STATUS_V(status)) {
2177 * We used to make lockread a blocking lock. It turns out
2178 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2182 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2184 * A blocking lock was requested. Package up
2185 * this smb into a queued request and push it
2186 * onto the blocking lock queue.
2188 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2189 (SMB_BIG_UINT)numtoread)) {
2190 END_PROFILE(SMBlockread);
2195 END_PROFILE(SMBlockread);
2196 return ERROR_NT(status);
2200 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2203 if (numtoread > max_recv) {
2204 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2205 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2206 (unsigned int)numtoread, (unsigned int)max_recv ));
2207 numtoread = MIN(numtoread,max_recv);
2209 nread = read_file(fsp,data,startpos,numtoread);
2212 END_PROFILE(SMBlockread);
2213 return(UNIXERROR(ERRDOS,ERRnoaccess));
2217 SSVAL(outbuf,smb_vwv0,nread);
2218 SSVAL(outbuf,smb_vwv5,nread+3);
2219 SSVAL(smb_buf(outbuf),1,nread);
2221 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2222 fsp->fnum, (int)numtoread, (int)nread));
2224 END_PROFILE(SMBlockread);
2229 #define DBGC_CLASS DBGC_ALL
2231 /****************************************************************************
2233 ****************************************************************************/
2235 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2242 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2243 START_PROFILE(SMBread);
2245 CHECK_FSP(fsp,conn);
2248 numtoread = SVAL(inbuf,smb_vwv1);
2249 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2251 outsize = set_message(outbuf,5,3,True);
2252 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2254 * The requested read size cannot be greater than max_recv. JRA.
2256 if (numtoread > max_recv) {
2257 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2258 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2259 (unsigned int)numtoread, (unsigned int)max_recv ));
2260 numtoread = MIN(numtoread,max_recv);
2263 data = smb_buf(outbuf) + 3;
2265 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2266 END_PROFILE(SMBread);
2267 return ERROR_DOS(ERRDOS,ERRlock);
2271 nread = read_file(fsp,data,startpos,numtoread);
2274 END_PROFILE(SMBread);
2275 return(UNIXERROR(ERRDOS,ERRnoaccess));
2279 SSVAL(outbuf,smb_vwv0,nread);
2280 SSVAL(outbuf,smb_vwv5,nread+3);
2281 SCVAL(smb_buf(outbuf),0,1);
2282 SSVAL(smb_buf(outbuf),1,nread);
2284 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2285 fsp->fnum, (int)numtoread, (int)nread ) );
2287 END_PROFILE(SMBread);
2291 /****************************************************************************
2292 Reply to a read and X - possibly using sendfile.
2293 ****************************************************************************/
2295 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2296 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2300 char *data = smb_buf(outbuf);
2302 #if defined(WITH_SENDFILE)
2304 * We can only use sendfile on a non-chained packet
2305 * but we can use on a non-oplocked file. tridge proved this
2306 * on a train in Germany :-). JRA.
2309 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2310 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2311 SMB_STRUCT_STAT sbuf;
2314 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2315 return(UNIXERROR(ERRDOS,ERRnoaccess));
2317 if (startpos > sbuf.st_size)
2320 if (smb_maxcnt > (sbuf.st_size - startpos))
2321 smb_maxcnt = (sbuf.st_size - startpos);
2323 if (smb_maxcnt == 0)
2327 * Set up the packet header before send. We
2328 * assume here the sendfile will work (get the
2329 * correct amount of data).
2332 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2333 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2334 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2335 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2336 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2337 SCVAL(outbuf,smb_vwv0,0xFF);
2338 set_message(outbuf,12,smb_maxcnt,False);
2339 header.data = outbuf;
2340 header.length = data - outbuf;
2343 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2344 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2345 if (errno == ENOSYS) {
2350 * Special hack for broken Linux with no working sendfile. If we
2351 * return EINTR we sent the header but not the rest of the data.
2352 * Fake this up by doing read/write calls.
2355 if (errno == EINTR) {
2356 /* Ensure we don't do this again. */
2357 set_use_sendfile(SNUM(conn), False);
2358 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2360 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2361 len_outbuf - (data-outbuf))) == -1) {
2362 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2363 fsp->fsp_name, strerror(errno) ));
2364 exit_server("send_file_readX: fake_sendfile failed");
2366 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2367 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2368 /* Returning -1 here means successful sendfile. */
2372 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2373 fsp->fsp_name, strerror(errno) ));
2374 exit_server("send_file_readX sendfile failed");
2377 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2378 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2379 /* Returning -1 here means successful sendfile. */
2387 nread = read_file(fsp,data,startpos,smb_maxcnt);
2390 END_PROFILE(SMBreadX);
2391 return(UNIXERROR(ERRDOS,ERRnoaccess));
2394 outsize = set_message(outbuf,12,nread,False);
2395 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2396 SSVAL(outbuf,smb_vwv5,nread);
2397 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2398 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2399 SSVAL(smb_buf(outbuf),-2,nread);
2401 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2402 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2404 /* Returning the number of bytes we want to send back - including header. */
2408 /****************************************************************************
2409 Reply to a read and X.
2410 ****************************************************************************/
2412 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2414 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2415 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2417 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2419 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2422 START_PROFILE(SMBreadX);
2424 /* If it's an IPC, pass off the pipe handler. */
2426 END_PROFILE(SMBreadX);
2427 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2430 CHECK_FSP(fsp,conn);
2433 set_message(outbuf,12,0,True);
2435 if (global_client_caps & CAP_LARGE_READX) {
2436 if (SVAL(inbuf,smb_vwv7) == 1) {
2437 smb_maxcnt |= (1<<16);
2439 if (smb_maxcnt > BUFFER_SIZE) {
2440 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2441 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2442 END_PROFILE(SMBreadX);
2443 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2447 if(CVAL(inbuf,smb_wct) == 12) {
2448 #ifdef LARGE_SMB_OFF_T
2450 * This is a large offset (64 bit) read.
2452 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2454 #else /* !LARGE_SMB_OFF_T */
2457 * Ensure we haven't been sent a >32 bit offset.
2460 if(IVAL(inbuf,smb_vwv10) != 0) {
2461 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2462 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2463 END_PROFILE(SMBreadX);
2464 return ERROR_DOS(ERRDOS,ERRbadaccess);
2467 #endif /* LARGE_SMB_OFF_T */
2471 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2472 END_PROFILE(SMBreadX);
2473 return ERROR_DOS(ERRDOS,ERRlock);
2476 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2478 nread = chain_reply(inbuf,outbuf,length,bufsize);
2480 END_PROFILE(SMBreadX);
2484 /****************************************************************************
2485 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2486 ****************************************************************************/
2488 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2491 ssize_t total_written=0;
2492 size_t numtowrite=0;
2497 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2499 START_PROFILE(SMBwritebraw);
2501 if (srv_is_signing_active()) {
2502 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2505 CHECK_FSP(fsp,conn);
2508 tcount = IVAL(inbuf,smb_vwv1);
2509 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2510 write_through = BITSETW(inbuf+smb_vwv7,0);
2512 /* We have to deal with slightly different formats depending
2513 on whether we are using the core+ or lanman1.0 protocol */
2515 if(Protocol <= PROTOCOL_COREPLUS) {
2516 numtowrite = SVAL(smb_buf(inbuf),-2);
2517 data = smb_buf(inbuf);
2519 numtowrite = SVAL(inbuf,smb_vwv10);
2520 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2523 /* force the error type */
2524 SCVAL(inbuf,smb_com,SMBwritec);
2525 SCVAL(outbuf,smb_com,SMBwritec);
2527 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2528 END_PROFILE(SMBwritebraw);
2529 return(ERROR_DOS(ERRDOS,ERRlock));
2533 nwritten = write_file(fsp,data,startpos,numtowrite);
2535 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2536 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2538 if (nwritten < (ssize_t)numtowrite) {
2539 END_PROFILE(SMBwritebraw);
2540 return(UNIXERROR(ERRHRD,ERRdiskfull));
2543 total_written = nwritten;
2545 /* Return a message to the redirector to tell it to send more bytes */
2546 SCVAL(outbuf,smb_com,SMBwritebraw);
2547 SSVALS(outbuf,smb_vwv0,-1);
2548 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2549 if (!send_smb(smbd_server_fd(),outbuf))
2550 exit_server("reply_writebraw: send_smb failed.");
2552 /* Now read the raw data into the buffer and write it */
2553 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2554 exit_server("secondary writebraw failed");
2557 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2558 numtowrite = smb_len(inbuf);
2560 /* Set up outbuf to return the correct return */
2561 outsize = set_message(outbuf,1,0,True);
2562 SCVAL(outbuf,smb_com,SMBwritec);
2563 SSVAL(outbuf,smb_vwv0,total_written);
2565 if (numtowrite != 0) {
2567 if (numtowrite > BUFFER_SIZE) {
2568 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2569 (unsigned int)numtowrite ));
2570 exit_server("secondary writebraw failed");
2573 if (tcount > nwritten+numtowrite) {
2574 DEBUG(3,("Client overestimated the write %d %d %d\n",
2575 (int)tcount,(int)nwritten,(int)numtowrite));
2578 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2579 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2581 exit_server("secondary writebraw failed");
2584 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2586 if (nwritten < (ssize_t)numtowrite) {
2587 SCVAL(outbuf,smb_rcls,ERRHRD);
2588 SSVAL(outbuf,smb_err,ERRdiskfull);
2592 total_written += nwritten;
2595 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2596 sync_file(conn,fsp);
2598 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2599 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2601 /* we won't return a status if write through is not selected - this follows what WfWg does */
2602 END_PROFILE(SMBwritebraw);
2603 if (!write_through && total_written==tcount) {
2605 #if RABBIT_PELLET_FIX
2607 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2608 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2610 if (!send_keepalive(smbd_server_fd()))
2611 exit_server("reply_writebraw: send of keepalive failed");
2620 #define DBGC_CLASS DBGC_LOCKING
2622 /****************************************************************************
2623 Reply to a writeunlock (core+).
2624 ****************************************************************************/
2626 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2627 int size, int dum_buffsize)
2629 ssize_t nwritten = -1;
2633 NTSTATUS status = NT_STATUS_OK;
2634 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2636 START_PROFILE(SMBwriteunlock);
2638 CHECK_FSP(fsp,conn);
2641 numtowrite = SVAL(inbuf,smb_vwv1);
2642 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2643 data = smb_buf(inbuf) + 3;
2645 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2646 END_PROFILE(SMBwriteunlock);
2647 return ERROR_DOS(ERRDOS,ERRlock);
2650 /* The special X/Open SMB protocol handling of
2651 zero length writes is *NOT* done for
2656 nwritten = write_file(fsp,data,startpos,numtowrite);
2658 if (lp_syncalways(SNUM(conn)))
2659 sync_file(conn,fsp);
2661 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2662 END_PROFILE(SMBwriteunlock);
2663 return(UNIXERROR(ERRHRD,ERRdiskfull));
2667 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2668 (SMB_BIG_UINT)startpos);
2669 if (NT_STATUS_V(status)) {
2670 END_PROFILE(SMBwriteunlock);
2671 return ERROR_NT(status);
2675 outsize = set_message(outbuf,1,0,True);
2677 SSVAL(outbuf,smb_vwv0,nwritten);
2679 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2680 fsp->fnum, (int)numtowrite, (int)nwritten));
2682 END_PROFILE(SMBwriteunlock);
2687 #define DBGC_CLASS DBGC_ALL
2689 /****************************************************************************
2691 ****************************************************************************/
2693 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2696 ssize_t nwritten = -1;
2699 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2701 START_PROFILE(SMBwrite);
2703 /* If it's an IPC, pass off the pipe handler. */
2705 END_PROFILE(SMBwrite);
2706 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2709 CHECK_FSP(fsp,conn);
2712 numtowrite = SVAL(inbuf,smb_vwv1);
2713 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2714 data = smb_buf(inbuf) + 3;
2716 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2717 END_PROFILE(SMBwrite);
2718 return ERROR_DOS(ERRDOS,ERRlock);
2722 * X/Open SMB protocol says that if smb_vwv1 is
2723 * zero then the file size should be extended or
2724 * truncated to the size given in smb_vwv[2-3].
2727 if(numtowrite == 0) {
2729 * This is actually an allocate call, and set EOF. JRA.
2731 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2733 END_PROFILE(SMBwrite);
2734 return ERROR_NT(NT_STATUS_DISK_FULL);
2736 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2738 END_PROFILE(SMBwrite);
2739 return ERROR_NT(NT_STATUS_DISK_FULL);
2742 nwritten = write_file(fsp,data,startpos,numtowrite);
2744 if (lp_syncalways(SNUM(conn)))
2745 sync_file(conn,fsp);
2747 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2748 END_PROFILE(SMBwrite);
2749 return(UNIXERROR(ERRHRD,ERRdiskfull));
2752 outsize = set_message(outbuf,1,0,True);
2754 SSVAL(outbuf,smb_vwv0,nwritten);
2756 if (nwritten < (ssize_t)numtowrite) {
2757 SCVAL(outbuf,smb_rcls,ERRHRD);
2758 SSVAL(outbuf,smb_err,ERRdiskfull);
2761 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2763 END_PROFILE(SMBwrite);
2767 /****************************************************************************
2768 Reply to a write and X.
2769 ****************************************************************************/
2771 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2773 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2774 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2775 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2776 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2777 ssize_t nwritten = -1;
2778 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2779 unsigned int smblen = smb_len(inbuf);
2781 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2782 START_PROFILE(SMBwriteX);
2784 /* If it's an IPC, pass off the pipe handler. */
2786 END_PROFILE(SMBwriteX);
2787 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2790 CHECK_FSP(fsp,conn);
2793 /* Deal with possible LARGE_WRITEX */
2795 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2797 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2798 END_PROFILE(SMBwriteX);
2799 return ERROR_DOS(ERRDOS,ERRbadmem);
2802 data = smb_base(inbuf) + smb_doff;
2804 if(CVAL(inbuf,smb_wct) == 14) {
2805 #ifdef LARGE_SMB_OFF_T
2807 * This is a large offset (64 bit) write.
2809 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2811 #else /* !LARGE_SMB_OFF_T */
2814 * Ensure we haven't been sent a >32 bit offset.
2817 if(IVAL(inbuf,smb_vwv12) != 0) {
2818 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2819 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2820 END_PROFILE(SMBwriteX);
2821 return ERROR_DOS(ERRDOS,ERRbadaccess);
2824 #endif /* LARGE_SMB_OFF_T */
2827 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2828 END_PROFILE(SMBwriteX);
2829 return ERROR_DOS(ERRDOS,ERRlock);
2832 /* X/Open SMB protocol says that, unlike SMBwrite
2833 if the length is zero then NO truncation is
2834 done, just a write of zero. To truncate a file,
2840 nwritten = write_file(fsp,data,startpos,numtowrite);
2842 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2843 END_PROFILE(SMBwriteX);
2844 return(UNIXERROR(ERRHRD,ERRdiskfull));
2847 set_message(outbuf,6,0,True);
2849 SSVAL(outbuf,smb_vwv2,nwritten);
2851 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2853 if (nwritten < (ssize_t)numtowrite) {
2854 SCVAL(outbuf,smb_rcls,ERRHRD);
2855 SSVAL(outbuf,smb_err,ERRdiskfull);
2858 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2859 fsp->fnum, (int)numtowrite, (int)nwritten));
2861 if (lp_syncalways(SNUM(conn)) || write_through)
2862 sync_file(conn,fsp);
2864 END_PROFILE(SMBwriteX);
2865 return chain_reply(inbuf,outbuf,length,bufsize);
2868 /****************************************************************************
2870 ****************************************************************************/
2872 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2878 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2879 START_PROFILE(SMBlseek);
2881 CHECK_FSP(fsp,conn);
2883 flush_write_cache(fsp, SEEK_FLUSH);
2885 mode = SVAL(inbuf,smb_vwv1) & 3;
2886 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2887 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2896 res = fsp->pos + startpos;
2907 if (umode == SEEK_END) {
2908 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2909 if(errno == EINVAL) {
2910 SMB_OFF_T current_pos = startpos;
2911 SMB_STRUCT_STAT sbuf;
2913 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2914 END_PROFILE(SMBlseek);
2915 return(UNIXERROR(ERRDOS,ERRnoaccess));
2918 current_pos += sbuf.st_size;
2920 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2925 END_PROFILE(SMBlseek);
2926 return(UNIXERROR(ERRDOS,ERRnoaccess));
2932 outsize = set_message(outbuf,2,0,True);
2933 SIVAL(outbuf,smb_vwv0,res);
2935 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2936 fsp->fnum, (double)startpos, (double)res, mode));
2938 END_PROFILE(SMBlseek);
2942 /****************************************************************************
2944 ****************************************************************************/
2946 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2948 int outsize = set_message(outbuf,0,0,True);
2949 uint16 fnum = SVAL(inbuf,smb_vwv0);
2950 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2951 START_PROFILE(SMBflush);
2954 CHECK_FSP(fsp,conn);
2957 file_sync_all(conn);
2959 sync_file(conn,fsp);
2962 DEBUG(3,("flush\n"));
2963 END_PROFILE(SMBflush);
2967 /****************************************************************************
2969 ****************************************************************************/
2971 int reply_exit(connection_struct *conn,
2972 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2975 START_PROFILE(SMBexit);
2977 file_close_pid(SVAL(inbuf,smb_pid));
2979 outsize = set_message(outbuf,0,0,True);
2981 DEBUG(3,("exit\n"));
2983 END_PROFILE(SMBexit);
2987 /****************************************************************************
2988 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2989 ****************************************************************************/
2991 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2996 int32 eclass = 0, err = 0;
2997 files_struct *fsp = NULL;
2998 START_PROFILE(SMBclose);
3000 outsize = set_message(outbuf,0,0,True);
3002 /* If it's an IPC, pass off to the pipe handler. */
3004 END_PROFILE(SMBclose);
3005 return reply_pipe_close(conn, inbuf,outbuf);
3008 fsp = file_fsp(inbuf,smb_vwv0);
3011 * We can only use CHECK_FSP if we know it's not a directory.
3014 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3015 END_PROFILE(SMBclose);
3016 return ERROR_DOS(ERRDOS,ERRbadfid);
3019 if(fsp->is_directory) {
3021 * Special case - close NT SMB directory handle.
3023 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3024 close_file(fsp,True);
3027 * Close ordinary file.
3032 /* Save the name for time set in close. */
3033 pstrcpy( file_name, fsp->fsp_name);
3035 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3037 conn->num_files_open));
3040 * Take care of any time sent in the close.
3043 mtime = make_unix_date3(inbuf+smb_vwv1);
3044 fsp_set_pending_modtime(fsp, mtime);
3047 * close_file() returns the unix errno if an error
3048 * was detected on close - normally this is due to
3049 * a disk full error. If not then it was probably an I/O error.
3052 if((close_err = close_file(fsp,True)) != 0) {
3054 END_PROFILE(SMBclose);
3055 return (UNIXERROR(ERRHRD,ERRgeneral));
3059 /* We have a cached error */
3061 END_PROFILE(SMBclose);
3062 return ERROR_DOS(eclass,err);
3065 END_PROFILE(SMBclose);
3069 /****************************************************************************
3070 Reply to a writeclose (Core+ protocol).
3071 ****************************************************************************/
3073 int reply_writeclose(connection_struct *conn,
3074 char *inbuf,char *outbuf, int size, int dum_buffsize)
3077 ssize_t nwritten = -1;
3083 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3084 START_PROFILE(SMBwriteclose);
3086 CHECK_FSP(fsp,conn);
3089 numtowrite = SVAL(inbuf,smb_vwv1);
3090 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3091 mtime = make_unix_date3(inbuf+smb_vwv4);
3092 data = smb_buf(inbuf) + 1;
3094 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3095 END_PROFILE(SMBwriteclose);
3096 return ERROR_DOS(ERRDOS,ERRlock);
3099 nwritten = write_file(fsp,data,startpos,numtowrite);
3101 set_filetime(conn, fsp->fsp_name,mtime);
3104 * More insanity. W2K only closes the file if writelen > 0.
3109 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3111 close_err = close_file(fsp,True);
3114 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3115 fsp->fnum, (int)numtowrite, (int)nwritten,
3116 conn->num_files_open));
3118 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3119 END_PROFILE(SMBwriteclose);
3120 return(UNIXERROR(ERRHRD,ERRdiskfull));
3123 if(close_err != 0) {
3125 END_PROFILE(SMBwriteclose);
3126 return(UNIXERROR(ERRHRD,ERRgeneral));
3129 outsize = set_message(outbuf,1,0,True);
3131 SSVAL(outbuf,smb_vwv0,nwritten);
3132 END_PROFILE(SMBwriteclose);
3137 #define DBGC_CLASS DBGC_LOCKING
3139 /****************************************************************************
3141 ****************************************************************************/
3143 int reply_lock(connection_struct *conn,
3144 char *inbuf,char *outbuf, int length, int dum_buffsize)
3146 int outsize = set_message(outbuf,0,0,True);
3147 SMB_BIG_UINT count,offset;
3149 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3150 BOOL my_lock_ctx = False;
3152 START_PROFILE(SMBlock);
3154 CHECK_FSP(fsp,conn);
3156 release_level_2_oplocks_on_change(fsp);
3158 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3159 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3161 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3162 fsp->fd, fsp->fnum, (double)offset, (double)count));
3164 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3165 if (NT_STATUS_V(status)) {
3167 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3168 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3170 * A blocking lock was requested. Package up
3171 * this smb into a queued request and push it
3172 * onto the blocking lock queue.
3174 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3175 END_PROFILE(SMBlock);
3180 END_PROFILE(SMBlock);
3181 return ERROR_NT(status);
3184 END_PROFILE(SMBlock);
3188 /****************************************************************************
3190 ****************************************************************************/
3192 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3195 int outsize = set_message(outbuf,0,0,True);
3196 SMB_BIG_UINT count,offset;
3198 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3199 START_PROFILE(SMBunlock);
3201 CHECK_FSP(fsp,conn);
3203 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3204 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3206 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3207 if (NT_STATUS_V(status)) {
3208 END_PROFILE(SMBunlock);
3209 return ERROR_NT(status);
3212 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3213 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3215 END_PROFILE(SMBunlock);
3220 #define DBGC_CLASS DBGC_ALL
3222 /****************************************************************************
3224 ****************************************************************************/
3226 int reply_tdis(connection_struct *conn,
3227 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3229 int outsize = set_message(outbuf,0,0,True);
3231 START_PROFILE(SMBtdis);
3233 vuid = SVAL(inbuf,smb_uid);
3236 DEBUG(4,("Invalid connection in tdis\n"));
3237 END_PROFILE(SMBtdis);
3238 return ERROR_DOS(ERRSRV,ERRinvnid);
3243 close_cnum(conn,vuid);
3245 END_PROFILE(SMBtdis);
3249 /****************************************************************************
3251 ****************************************************************************/
3253 int reply_echo(connection_struct *conn,
3254 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3256 int smb_reverb = SVAL(inbuf,smb_vwv0);
3258 unsigned int data_len = smb_buflen(inbuf);
3259 int outsize = set_message(outbuf,1,data_len,True);
3260 START_PROFILE(SMBecho);
3262 if (data_len > BUFFER_SIZE) {
3263 DEBUG(0,("reply_echo: data_len too large.\n"));
3264 END_PROFILE(SMBecho);
3268 /* copy any incoming data back out */
3270 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3272 if (smb_reverb > 100) {
3273 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3277 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3278 SSVAL(outbuf,smb_vwv0,seq_num);
3280 smb_setlen(outbuf,outsize - 4);
3282 if (!send_smb(smbd_server_fd(),outbuf))
3283 exit_server("reply_echo: send_smb failed.");
3286 DEBUG(3,("echo %d times\n", smb_reverb));
3290 END_PROFILE(SMBecho);
3294 /****************************************************************************
3295 Reply to a printopen.
3296 ****************************************************************************/
3298 int reply_printopen(connection_struct *conn,
3299 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3303 START_PROFILE(SMBsplopen);
3305 if (!CAN_PRINT(conn)) {
3306 END_PROFILE(SMBsplopen);
3307 return ERROR_DOS(ERRDOS,ERRnoaccess);
3310 /* Open for exclusive use, write only. */
3311 fsp = print_fsp_open(conn, NULL);
3314 END_PROFILE(SMBsplopen);
3315 return(UNIXERROR(ERRDOS,ERRnoaccess));
3318 outsize = set_message(outbuf,1,0,True);
3319 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3321 DEBUG(3,("openprint fd=%d fnum=%d\n",
3322 fsp->fd, fsp->fnum));
3324 END_PROFILE(SMBsplopen);
3328 /****************************************************************************
3329 Reply to a printclose.
3330 ****************************************************************************/
3332 int reply_printclose(connection_struct *conn,
3333 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3335 int outsize = set_message(outbuf,0,0,True);
3336 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3338 START_PROFILE(SMBsplclose);
3340 CHECK_FSP(fsp,conn);
3342 if (!CAN_PRINT(conn)) {
3343 END_PROFILE(SMBsplclose);
3344 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3347 DEBUG(3,("printclose fd=%d fnum=%d\n",
3348 fsp->fd,fsp->fnum));
3350 close_err = close_file(fsp,True);
3352 if(close_err != 0) {
3354 END_PROFILE(SMBsplclose);
3355 return(UNIXERROR(ERRHRD,ERRgeneral));
3358 END_PROFILE(SMBsplclose);
3362 /****************************************************************************
3363 Reply to a printqueue.
3364 ****************************************************************************/
3366 int reply_printqueue(connection_struct *conn,
3367 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3369 int outsize = set_message(outbuf,2,3,True);
3370 int max_count = SVAL(inbuf,smb_vwv0);
3371 int start_index = SVAL(inbuf,smb_vwv1);
3372 START_PROFILE(SMBsplretq);
3374 /* we used to allow the client to get the cnum wrong, but that
3375 is really quite gross and only worked when there was only
3376 one printer - I think we should now only accept it if they
3377 get it right (tridge) */
3378 if (!CAN_PRINT(conn)) {
3379 END_PROFILE(SMBsplretq);
3380 return ERROR_DOS(ERRDOS,ERRnoaccess);
3383 SSVAL(outbuf,smb_vwv0,0);
3384 SSVAL(outbuf,smb_vwv1,0);
3385 SCVAL(smb_buf(outbuf),0,1);
3386 SSVAL(smb_buf(outbuf),1,0);
3388 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3389 start_index, max_count));
3392 print_queue_struct *queue = NULL;
3393 print_status_struct status;
3394 char *p = smb_buf(outbuf) + 3;
3395 int count = print_queue_status(SNUM(conn), &queue, &status);
3396 int num_to_get = ABS(max_count);
3397 int first = (max_count>0?start_index:start_index+max_count+1);
3403 num_to_get = MIN(num_to_get,count-first);
3406 for (i=first;i<first+num_to_get;i++) {
3407 put_dos_date2(p,0,queue[i].time);
3408 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3409 SSVAL(p,5, queue[i].job);
3410 SIVAL(p,7,queue[i].size);
3412 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3417 outsize = set_message(outbuf,2,28*count+3,False);
3418 SSVAL(outbuf,smb_vwv0,count);
3419 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3420 SCVAL(smb_buf(outbuf),0,1);
3421 SSVAL(smb_buf(outbuf),1,28*count);
3426 DEBUG(3,("%d entries returned in queue\n",count));
3429 END_PROFILE(SMBsplretq);
3433 /****************************************************************************
3434 Reply to a printwrite.
3435 ****************************************************************************/
3437 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3440 int outsize = set_message(outbuf,0,0,True);
3442 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3444 START_PROFILE(SMBsplwr);
3446 if (!CAN_PRINT(conn)) {
3447 END_PROFILE(SMBsplwr);
3448 return ERROR_DOS(ERRDOS,ERRnoaccess);
3451 CHECK_FSP(fsp,conn);
3454 numtowrite = SVAL(smb_buf(inbuf),1);
3455 data = smb_buf(inbuf) + 3;
3457 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3458 END_PROFILE(SMBsplwr);
3459 return(UNIXERROR(ERRHRD,ERRdiskfull));
3462 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3464 END_PROFILE(SMBsplwr);
3468 /****************************************************************************
3469 The guts of the mkdir command, split out so it may be called by the NT SMB
3471 ****************************************************************************/
3473 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3477 if(!CAN_WRITE(conn)) {
3478 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3480 return map_nt_error_from_unix(errno);
3484 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3487 if (!check_name(directory, conn)) {
3488 if(errno == ENOENT) {
3490 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3492 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3495 return map_nt_error_from_unix(errno);
3498 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3500 if(errno == ENOENT) {
3501 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3503 return map_nt_error_from_unix(errno);
3506 return NT_STATUS_OK;
3509 /****************************************************************************
3511 ****************************************************************************/
3513 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3518 BOOL bad_path = False;
3519 SMB_STRUCT_STAT sbuf;
3521 START_PROFILE(SMBmkdir);
3523 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3524 if (!NT_STATUS_IS_OK(status)) {
3525 END_PROFILE(SMBmkdir);
3526 return ERROR_NT(status);
3529 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3531 unix_convert(directory,conn,0,&bad_path,&sbuf);
3533 if( strchr_m(directory, ':')) {
3534 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3535 END_PROFILE(SMBmkdir);
3536 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3539 status = mkdir_internal(conn, directory,bad_path);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 END_PROFILE(SMBmkdir);
3542 return ERROR_NT(status);
3545 if (lp_inherit_owner(SNUM(conn))) {
3546 /* Ensure we're checking for a symlink here.... */
3547 /* We don't want to get caught by a symlink racer. */
3549 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3550 END_PROFILE(SMBmkdir);
3551 return(UNIXERROR(ERRDOS,ERRnoaccess));
3554 if(!S_ISDIR(sbuf.st_mode)) {
3555 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3556 END_PROFILE(SMBmkdir);
3557 return(UNIXERROR(ERRDOS,ERRnoaccess));
3560 change_owner_to_parent(conn, NULL, directory, &sbuf);
3563 outsize = set_message(outbuf,0,0,True);
3565 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3567 END_PROFILE(SMBmkdir);
3571 /****************************************************************************
3572 Static function used by reply_rmdir to delete an entire directory
3573 tree recursively. Return False on ok, True on fail.
3574 ****************************************************************************/
3576 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3578 const char *dname = NULL;
3581 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3586 while((dname = ReadDirName(dir_hnd, &offset))) {
3590 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3593 if (!is_visible_file(conn, directory, dname, &st, False))
3596 /* Construct the full name. */
3597 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3603 pstrcpy(fullname, directory);
3604 pstrcat(fullname, "/");
3605 pstrcat(fullname, dname);
3607 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3612 if(st.st_mode & S_IFDIR) {
3613 if(recursive_rmdir(conn, fullname)!=0) {
3617 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3621 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3630 /****************************************************************************
3631 The internals of the rmdir code - called elsewhere.
3632 ****************************************************************************/
3634 BOOL rmdir_internals(connection_struct *conn, char *directory)
3639 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3640 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3642 * Check to see if the only thing in this directory are
3643 * vetoed files/directories. If so then delete them and
3644 * retry. If we fail to delete any of them (and we *don't*
3645 * do a recursive delete) then fail the rmdir.
3647 BOOL all_veto_files = True;
3649 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3651 if(dir_hnd != NULL) {
3652 long dirpos = TellDir(dir_hnd);
3653 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3654 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3656 if (!is_visible_file(conn, directory, dname, &st, False))
3658 if(!IS_VETO_PATH(conn, dname)) {
3659 all_veto_files = False;
3664 if(all_veto_files) {
3665 SeekDir(dir_hnd,dirpos);
3666 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3669 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3671 if (!is_visible_file(conn, directory, dname, &st, False))
3674 /* Construct the full name. */
3675 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3680 pstrcpy(fullname, directory);
3681 pstrcat(fullname, "/");
3682 pstrcat(fullname, dname);
3684 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3686 if(st.st_mode & S_IFDIR) {
3687 if(lp_recursive_veto_delete(SNUM(conn))) {
3688 if(recursive_rmdir(conn, fullname) != 0)
3691 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3693 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3697 /* Retry the rmdir */
3698 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3708 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3713 /****************************************************************************
3715 ****************************************************************************/
3717 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3722 BOOL bad_path = False;
3723 SMB_STRUCT_STAT sbuf;
3725 START_PROFILE(SMBrmdir);
3727 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3728 if (!NT_STATUS_IS_OK(status)) {
3729 END_PROFILE(SMBrmdir);
3730 return ERROR_NT(status);
3733 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3735 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3737 END_PROFILE(SMBrmdir);
3738 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3741 if (check_name(directory,conn)) {
3742 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3743 ok = rmdir_internals(conn, directory);
3747 END_PROFILE(SMBrmdir);
3748 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3751 outsize = set_message(outbuf,0,0,True);
3753 DEBUG( 3, ( "rmdir %s\n", directory ) );
3755 END_PROFILE(SMBrmdir);
3759 /*******************************************************************
3760 Resolve wildcards in a filename rename.
3761 Note that name is in UNIX charset and thus potentially can be more
3762 than fstring buffer (255 bytes) especially in default UTF-8 case.
3763 Therefore, we use pstring inside and all calls should ensure that
3764 name2 is at least pstring-long (they do already)
3765 ********************************************************************/
3767 static BOOL resolve_wildcards(const char *name1, char *name2)
3769 pstring root1,root2;
3771 char *p,*p2, *pname1, *pname2;
3772 int available_space, actual_space;
3775 pname1 = strrchr_m(name1,'/');
3776 pname2 = strrchr_m(name2,'/');
3778 if (!pname1 || !pname2)
3781 pstrcpy(root1,pname1);
3782 pstrcpy(root2,pname2);
3783 p = strrchr_m(root1,'.');
3790 p = strrchr_m(root2,'.');
3804 } else if (*p2 == '*') {
3820 } else if (*p2 == '*') {
3830 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3833 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3834 if (actual_space >= available_space - 1) {
3835 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3836 actual_space - available_space));
3839 pstrcpy_base(pname2, root2, name2);
3845 /****************************************************************************
3846 Ensure open files have their names updates.
3847 ****************************************************************************/
3849 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3852 BOOL did_rename = False;
3854 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3855 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3856 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3857 fsp->fsp_name, newname ));
3858 string_set(&fsp->fsp_name, newname);
3863 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3864 (unsigned int)dev, (double)inode, newname ));
3867 /****************************************************************************
3868 Rename an open file - given an fsp.
3869 ****************************************************************************/
3871 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3873 SMB_STRUCT_STAT sbuf;
3874 BOOL bad_path = False;
3875 pstring newname_last_component;
3876 NTSTATUS error = NT_STATUS_OK;
3881 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3883 /* Quick check for "." and ".." */
3884 if (!bad_path && newname_last_component[0] == '.') {
3885 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3886 return NT_STATUS_ACCESS_DENIED;
3889 if (!rcdest && bad_path) {
3890 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3893 /* Ensure newname contains a '/' */
3894 if(strrchr_m(newname,'/') == 0) {
3897 pstrcpy(tmpstr, "./");
3898 pstrcat(tmpstr, newname);
3899 pstrcpy(newname, tmpstr);
3903 * Check for special case with case preserving and not
3904 * case sensitive. If the old last component differs from the original
3905 * last component only by case, then we should allow
3906 * the rename (user is trying to change the case of the
3910 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3911 strequal(newname, fsp->fsp_name)) {
3913 pstring newname_modified_last_component;
3916 * Get the last component of the modified name.
3917 * Note that we guarantee that newname contains a '/'
3920 p = strrchr_m(newname,'/');
3921 pstrcpy(newname_modified_last_component,p+1);
3923 if(strcsequal(newname_modified_last_component,
3924 newname_last_component) == False) {
3926 * Replace the modified last component with
3929 pstrcpy(p+1, newname_last_component);
3934 * If the src and dest names are identical - including case,
3935 * don't do the rename, just return success.
3938 if (strcsequal(fsp->fsp_name, newname)) {
3939 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3941 return NT_STATUS_OK;
3944 dest_exists = vfs_object_exist(conn,newname,NULL);
3946 if(!replace_if_exists && dest_exists) {
3947 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3948 fsp->fsp_name,newname));
3949 return NT_STATUS_OBJECT_NAME_COLLISION;
3952 error = can_rename(conn,newname,attrs,&sbuf);
3954 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3955 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3956 nt_errstr(error), fsp->fsp_name,newname));
3957 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3958 error = NT_STATUS_ACCESS_DENIED;
3962 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3963 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3964 fsp->fsp_name,newname));
3965 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3966 return NT_STATUS_OK;
3969 if (errno == ENOTDIR || errno == EISDIR)
3970 error = NT_STATUS_OBJECT_NAME_COLLISION;
3972 error = map_nt_error_from_unix(errno);
3974 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3975 nt_errstr(error), fsp->fsp_name,newname));
3980 /****************************************************************************
3981 The guts of the rename command, split out so it may be called by the NT SMB
3983 ****************************************************************************/
3985 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3989 pstring last_component_src;
3990 pstring last_component_dest;
3993 BOOL bad_path_src = False;
3994 BOOL bad_path_dest = False;
3996 NTSTATUS error = NT_STATUS_OK;
3999 SMB_STRUCT_STAT sbuf1, sbuf2;
4001 *directory = *mask = 0;
4006 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4007 if (!rc && bad_path_src) {
4008 if (ms_has_wild(last_component_src))
4009 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4010 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4013 /* Quick check for "." and ".." */
4014 if (last_component_src[0] == '.') {
4015 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4016 return NT_STATUS_OBJECT_NAME_INVALID;
4020 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4022 /* Quick check for "." and ".." */
4023 if (last_component_dest[0] == '.') {
4024 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4025 return NT_STATUS_OBJECT_NAME_INVALID;
4030 * Split the old name into directory and last component
4031 * strings. Note that unix_convert may have stripped off a
4032 * leading ./ from both name and newname if the rename is
4033 * at the root of the share. We need to make sure either both
4034 * name and newname contain a / character or neither of them do
4035 * as this is checked in resolve_wildcards().
4038 p = strrchr_m(name,'/');
4040 pstrcpy(directory,".");
4044 pstrcpy(directory,name);
4046 *p = '/'; /* Replace needed for exceptional test below. */
4050 * We should only check the mangled cache
4051 * here if unix_convert failed. This means
4052 * that the path in 'mask' doesn't exist
4053 * on the file system and so we need to look
4054 * for a possible mangle. This patch from
4055 * Tine Smukavec <valentin.smukavec@hermes.si>.
4058 if (!rc && mangle_is_mangled(mask))
4059 mangle_check_cache( mask, sizeof(pstring)-1 );
4061 has_wild = ms_has_wild(mask);
4065 * No wildcards - just process the one file.
4067 BOOL is_short_name = mangle_is_8_3(name, True);
4069 /* Add a terminating '/' to the directory name. */
4070 pstrcat(directory,"/");
4071 pstrcat(directory,mask);
4073 /* Ensure newname contains a '/' also */
4074 if(strrchr_m(newname,'/') == 0) {
4077 pstrcpy(tmpstr, "./");
4078 pstrcat(tmpstr, newname);
4079 pstrcpy(newname, tmpstr);
4082 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4083 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4084 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4085 newname, last_component_dest, is_short_name));
4088 * Check for special case with case preserving and not
4089 * case sensitive, if directory and newname are identical,
4090 * and the old last component differs from the original
4091 * last component only by case, then we should allow
4092 * the rename (user is trying to change the case of the
4095 if((conn->case_sensitive == False) &&
4096 (((conn->case_preserve == True) &&
4097 (is_short_name == False)) ||
4098 ((conn->short_case_preserve == True) &&
4099 (is_short_name == True))) &&
4100 strcsequal(directory, newname)) {
4101 pstring modified_last_component;
4104 * Get the last component of the modified name.
4105 * Note that we guarantee that newname contains a '/'
4108 p = strrchr_m(newname,'/');
4109 pstrcpy(modified_last_component,p+1);
4111 if(strcsequal(modified_last_component,
4112 last_component_dest) == False) {
4114 * Replace the modified last component with
4117 pstrcpy(p+1, last_component_dest);
4121 resolve_wildcards(directory,newname);
4124 * The source object must exist.
4127 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4128 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4129 directory,newname));
4131 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4133 * Must return different errors depending on whether the parent
4134 * directory existed or not.
4137 p = strrchr_m(directory, '/');
4139 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4141 if (vfs_object_exist(conn, directory, NULL))
4142 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4143 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4145 error = map_nt_error_from_unix(errno);
4146 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4147 nt_errstr(error), directory,newname));
4152 if (!rcdest && bad_path_dest) {
4153 if (ms_has_wild(last_component_dest))
4154 return NT_STATUS_OBJECT_NAME_INVALID;
4155 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4158 error = can_rename(conn,directory,attrs,&sbuf1);
4160 if (!NT_STATUS_IS_OK(error)) {
4161 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4162 nt_errstr(error), directory,newname));
4167 * If the src and dest names are identical - including case,
4168 * don't do the rename, just return success.
4171 if (strcsequal(directory, newname)) {
4172 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4173 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4174 return NT_STATUS_OK;
4177 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4178 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4179 directory,newname));
4180 return NT_STATUS_OBJECT_NAME_COLLISION;
4183 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4184 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4185 directory,newname));
4186 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4187 return NT_STATUS_OK;
4190 if (errno == ENOTDIR || errno == EISDIR)
4191 error = NT_STATUS_OBJECT_NAME_COLLISION;
4193 error = map_nt_error_from_unix(errno);
4195 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4196 nt_errstr(error), directory,newname));
4201 * Wildcards - process each file that matches.
4203 struct smb_Dir *dir_hnd = NULL;
4207 if (check_name(directory,conn))
4208 dir_hnd = OpenDir(conn, directory);
4212 error = NT_STATUS_NO_SUCH_FILE;
4213 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4215 if (strequal(mask,"????????.???"))
4218 while ((dname = ReadDirName(dir_hnd, &offset))) {
4220 BOOL sysdir_entry = False;
4222 pstrcpy(fname,dname);
4224 /* Quick check for "." and ".." */
4225 if (fname[0] == '.') {
4226 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4228 sysdir_entry = True;
4235 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4238 if(!mask_match(fname, mask, conn->case_sensitive))
4242 error = NT_STATUS_OBJECT_NAME_INVALID;
4246 error = NT_STATUS_ACCESS_DENIED;
4247 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4248 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4249 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4250 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4253 error = can_rename(conn,fname,attrs,&sbuf1);
4254 if (!NT_STATUS_IS_OK(error)) {
4255 DEBUG(6,("rename %s refused\n", fname));
4258 pstrcpy(destname,newname);
4260 if (!resolve_wildcards(fname,destname)) {
4261 DEBUG(6,("resolve_wildcards %s %s failed\n",
4266 if (strcsequal(fname,destname)) {
4267 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4268 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4270 error = NT_STATUS_OK;
4274 if (!replace_if_exists &&
4275 vfs_file_exist(conn,destname, NULL)) {
4276 DEBUG(6,("file_exist %s\n", destname));
4277 error = NT_STATUS_OBJECT_NAME_COLLISION;
4281 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4282 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4284 error = NT_STATUS_OK;
4286 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4291 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4292 if (!rcdest && bad_path_dest) {
4293 if (ms_has_wild(last_component_dest))
4294 return NT_STATUS_OBJECT_NAME_INVALID;
4295 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4300 if (count == 0 && NT_STATUS_IS_OK(error)) {
4301 error = map_nt_error_from_unix(errno);
4307 /****************************************************************************
4309 ****************************************************************************/
4311 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4318 uint16 attrs = SVAL(inbuf,smb_vwv0);
4321 START_PROFILE(SMBmv);
4323 p = smb_buf(inbuf) + 1;
4324 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4325 if (!NT_STATUS_IS_OK(status)) {
4327 return ERROR_NT(status);
4330 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4331 if (!NT_STATUS_IS_OK(status)) {
4333 return ERROR_NT(status);
4336 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4337 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4339 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4341 status = rename_internals(conn, name, newname, attrs, False);
4342 if (!NT_STATUS_IS_OK(status)) {
4344 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4345 /* We have re-scheduled this call. */
4348 return ERROR_NT(status);
4352 * Win2k needs a changenotify request response before it will
4353 * update after a rename..
4355 process_pending_change_notify_queue((time_t)0);
4356 outsize = set_message(outbuf,0,0,True);
4362 /*******************************************************************
4363 Copy a file as part of a reply_copy.
4364 ******************************************************************/
4366 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4367 int count,BOOL target_is_directory, int *err_ret)
4370 SMB_STRUCT_STAT src_sbuf, sbuf2;
4372 files_struct *fsp1,*fsp2;
4378 pstrcpy(dest,dest1);
4379 if (target_is_directory) {
4380 char *p = strrchr_m(src,'/');
4389 if (!vfs_file_exist(conn,src,&src_sbuf))
4392 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4393 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4399 if (!target_is_directory && count)
4400 ofun = FILE_EXISTS_OPEN;
4402 dosattrs = dos_mode(conn, src, &src_sbuf);
4403 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4404 ZERO_STRUCTP(&sbuf2);
4406 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4407 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4410 close_file(fsp1,False);
4414 if ((ofun&3) == 1) {
4415 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4416 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4418 * Stop the copy from occurring.
4421 src_sbuf.st_size = 0;
4425 if (src_sbuf.st_size)
4426 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4428 close_file(fsp1,False);
4430 /* Ensure the modtime is set correctly on the destination file. */
4431 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4434 * As we are opening fsp1 read-only we only expect
4435 * an error on close on fsp2 if we are out of space.
4436 * Thus we don't look at the error return from the
4439 *err_ret = close_file(fsp2,False);
4441 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4444 /****************************************************************************
4445 Reply to a file copy.
4446 ****************************************************************************/
4448 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4453 pstring mask,newname;
4456 int error = ERRnoaccess;
4460 int tid2 = SVAL(inbuf,smb_vwv0);
4461 int ofun = SVAL(inbuf,smb_vwv1);
4462 int flags = SVAL(inbuf,smb_vwv2);
4463 BOOL target_is_directory=False;
4464 BOOL bad_path1 = False;
4465 BOOL bad_path2 = False;
4467 SMB_STRUCT_STAT sbuf1, sbuf2;
4470 START_PROFILE(SMBcopy);
4472 *directory = *mask = 0;
4475 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4476 if (!NT_STATUS_IS_OK(status)) {
4477 END_PROFILE(SMBcopy);
4478 return ERROR_NT(status);
4480 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4481 if (!NT_STATUS_IS_OK(status)) {
4482 END_PROFILE(SMBcopy);
4483 return ERROR_NT(status);
4486 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4488 if (tid2 != conn->cnum) {
4489 /* can't currently handle inter share copies XXXX */
4490 DEBUG(3,("Rejecting inter-share copy\n"));
4491 END_PROFILE(SMBcopy);
4492 return ERROR_DOS(ERRSRV,ERRinvdevice);
4495 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4496 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4498 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4499 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4501 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4503 if ((flags&1) && target_is_directory) {
4504 END_PROFILE(SMBcopy);
4505 return ERROR_DOS(ERRDOS,ERRbadfile);
4508 if ((flags&2) && !target_is_directory) {
4509 END_PROFILE(SMBcopy);
4510 return ERROR_DOS(ERRDOS,ERRbadpath);
4513 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4514 /* wants a tree copy! XXXX */
4515 DEBUG(3,("Rejecting tree copy\n"));
4516 END_PROFILE(SMBcopy);
4517 return ERROR_DOS(ERRSRV,ERRerror);
4520 p = strrchr_m(name,'/');
4522 pstrcpy(directory,"./");
4526 pstrcpy(directory,name);
4531 * We should only check the mangled cache
4532 * here if unix_convert failed. This means
4533 * that the path in 'mask' doesn't exist
4534 * on the file system and so we need to look
4535 * for a possible mangle. This patch from
4536 * Tine Smukavec <valentin.smukavec@hermes.si>.
4539 if (!rc && mangle_is_mangled(mask))
4540 mangle_check_cache( mask, sizeof(pstring)-1 );
4542 has_wild = ms_has_wild(mask);
4545 pstrcat(directory,"/");
4546 pstrcat(directory,mask);
4547 if (resolve_wildcards(directory,newname) &&
4548 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4552 END_PROFILE(SMBcopy);
4553 return(UNIXERROR(ERRHRD,ERRgeneral));
4556 exists = vfs_file_exist(conn,directory,NULL);
4559 struct smb_Dir *dir_hnd = NULL;
4563 if (check_name(directory,conn))
4564 dir_hnd = OpenDir(conn, directory);
4570 if (strequal(mask,"????????.???"))
4573 while ((dname = ReadDirName(dir_hnd, &offset))) {
4575 pstrcpy(fname,dname);
4577 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4580 if(!mask_match(fname, mask, conn->case_sensitive))
4583 error = ERRnoaccess;
4584 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4585 pstrcpy(destname,newname);
4586 if (resolve_wildcards(fname,destname) &&
4587 copy_file(fname,destname,conn,ofun,
4588 count,target_is_directory,&err))
4590 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4598 /* Error on close... */
4600 END_PROFILE(SMBcopy);
4601 return(UNIXERROR(ERRHRD,ERRgeneral));
4605 END_PROFILE(SMBcopy);
4606 return ERROR_DOS(ERRDOS,error);
4608 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4609 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4611 END_PROFILE(SMBcopy);
4612 return(UNIXERROR(ERRDOS,error));
4616 outsize = set_message(outbuf,1,0,True);
4617 SSVAL(outbuf,smb_vwv0,count);
4619 END_PROFILE(SMBcopy);
4623 /****************************************************************************
4625 ****************************************************************************/
4627 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4635 START_PROFILE(pathworks_setdir);
4638 if (!CAN_SETDIR(snum)) {
4639 END_PROFILE(pathworks_setdir);
4640 return ERROR_DOS(ERRDOS,ERRnoaccess);
4643 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4644 if (!NT_STATUS_IS_OK(status)) {
4645 END_PROFILE(pathworks_setdir);
4646 return ERROR_NT(status);
4649 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4651 if (strlen(newdir) == 0) {
4654 ok = vfs_directory_exist(conn,newdir,NULL);
4656 string_set(&conn->connectpath,newdir);
4660 END_PROFILE(pathworks_setdir);
4661 return ERROR_DOS(ERRDOS,ERRbadpath);
4664 outsize = set_message(outbuf,0,0,True);
4665 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4667 DEBUG(3,("setdir %s\n", newdir));
4669 END_PROFILE(pathworks_setdir);
4674 #define DBGC_CLASS DBGC_LOCKING
4676 /****************************************************************************
4677 Get a lock pid, dealing with large count requests.
4678 ****************************************************************************/
4680 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4682 if(!large_file_format)
4683 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4685 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4688 /****************************************************************************
4689 Get a lock count, dealing with large count requests.
4690 ****************************************************************************/
4692 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4694 SMB_BIG_UINT count = 0;
4696 if(!large_file_format) {
4697 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4700 #if defined(HAVE_LONGLONG)
4701 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4702 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4703 #else /* HAVE_LONGLONG */
4706 * NT4.x seems to be broken in that it sends large file (64 bit)
4707 * lockingX calls even if the CAP_LARGE_FILES was *not*
4708 * negotiated. For boxes without large unsigned ints truncate the
4709 * lock count by dropping the top 32 bits.
4712 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4713 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4714 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4715 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4716 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4719 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4720 #endif /* HAVE_LONGLONG */
4726 #if !defined(HAVE_LONGLONG)
4727 /****************************************************************************
4728 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4729 ****************************************************************************/
4731 static uint32 map_lock_offset(uint32 high, uint32 low)
4735 uint32 highcopy = high;
4738 * Try and find out how many significant bits there are in high.
4741 for(i = 0; highcopy; i++)
4745 * We use 31 bits not 32 here as POSIX
4746 * lock offsets may not be negative.
4749 mask = (~0) << (31 - i);
4752 return 0; /* Fail. */
4758 #endif /* !defined(HAVE_LONGLONG) */
4760 /****************************************************************************
4761 Get a lock offset, dealing with large offset requests.
4762 ****************************************************************************/
4764 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4766 SMB_BIG_UINT offset = 0;
4770 if(!large_file_format) {
4771 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4774 #if defined(HAVE_LONGLONG)
4775 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4776 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4777 #else /* HAVE_LONGLONG */
4780 * NT4.x seems to be broken in that it sends large file (64 bit)
4781 * lockingX calls even if the CAP_LARGE_FILES was *not*
4782 * negotiated. For boxes without large unsigned ints mangle the
4783 * lock offset by mapping the top 32 bits onto the lower 32.
4786 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4787 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4788 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4791 if((new_low = map_lock_offset(high, low)) == 0) {
4793 return (SMB_BIG_UINT)-1;
4796 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4797 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4798 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4799 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4802 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4803 #endif /* HAVE_LONGLONG */
4809 /****************************************************************************
4810 Reply to a lockingX request.
4811 ****************************************************************************/
4813 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4815 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4816 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4817 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4818 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4819 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4820 SMB_BIG_UINT count = 0, offset = 0;
4822 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4825 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4827 BOOL my_lock_ctx = False;
4830 START_PROFILE(SMBlockingX);
4832 CHECK_FSP(fsp,conn);
4834 data = smb_buf(inbuf);
4836 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4837 /* we don't support these - and CANCEL_LOCK makes w2k
4838 and XP reboot so I don't really want to be
4839 compatible! (tridge) */
4840 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4843 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4844 /* Need to make this like a cancel.... JRA. */
4845 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4848 /* Check if this is an oplock break on a file
4849 we have granted an oplock on.
4851 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4852 /* Client can insist on breaking to none. */
4853 BOOL break_to_none = (oplocklevel == 0);
4855 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4856 (unsigned int)oplocklevel, fsp->fnum ));
4859 * Make sure we have granted an exclusive or batch oplock on this file.
4862 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4863 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4864 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4866 /* if this is a pure oplock break request then don't send a reply */
4867 if (num_locks == 0 && num_ulocks == 0) {
4868 END_PROFILE(SMBlockingX);
4871 END_PROFILE(SMBlockingX);
4872 return ERROR_DOS(ERRDOS,ERRlock);
4876 if (remove_oplock(fsp, break_to_none) == False) {
4877 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4881 /* if this is a pure oplock break request then don't send a reply */
4882 if (num_locks == 0 && num_ulocks == 0) {
4883 /* Sanity check - ensure a pure oplock break is not a
4885 if(CVAL(inbuf,smb_vwv0) != 0xff)
4886 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4887 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4888 END_PROFILE(SMBlockingX);
4894 * We do this check *after* we have checked this is not a oplock break
4895 * response message. JRA.
4898 release_level_2_oplocks_on_change(fsp);
4900 /* Data now points at the beginning of the list
4901 of smb_unlkrng structs */
4902 for(i = 0; i < (int)num_ulocks; i++) {
4903 lock_pid = get_lock_pid( data, i, large_file_format);
4904 count = get_lock_count( data, i, large_file_format);
4905 offset = get_lock_offset( data, i, large_file_format, &err);
4908 * There is no error code marked "stupid client bug".... :-).
4911 END_PROFILE(SMBlockingX);
4912 return ERROR_DOS(ERRDOS,ERRnoaccess);
4915 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4916 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4918 status = do_unlock(fsp,conn,lock_pid,count,offset);
4919 if (NT_STATUS_V(status)) {
4920 END_PROFILE(SMBlockingX);
4921 return ERROR_NT(status);
4925 /* Setup the timeout in seconds. */
4927 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4929 /* Now do any requested locks */
4930 data += ((large_file_format ? 20 : 10)*num_ulocks);
4932 /* Data now points at the beginning of the list
4933 of smb_lkrng structs */
4935 for(i = 0; i < (int)num_locks; i++) {
4936 lock_pid = get_lock_pid( data, i, large_file_format);
4937 count = get_lock_count( data, i, large_file_format);
4938 offset = get_lock_offset( data, i, large_file_format, &err);
4941 * There is no error code marked "stupid client bug".... :-).
4944 END_PROFILE(SMBlockingX);
4945 return ERROR_DOS(ERRDOS,ERRnoaccess);
4948 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4949 (double)offset, (double)count, (unsigned int)lock_pid,
4950 fsp->fsp_name, (int)lock_timeout ));
4952 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4953 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4954 if (NT_STATUS_V(status)) {
4956 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4957 * Even if it's our own lock context, we need to wait here as
4958 * there may be an unlock on the way.
4959 * So I removed a "&& !my_lock_ctx" from the following
4960 * if statement. JRA.
4962 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4964 * A blocking lock was requested. Package up
4965 * this smb into a queued request and push it
4966 * onto the blocking lock queue.
4968 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4969 END_PROFILE(SMBlockingX);
4977 /* If any of the above locks failed, then we must unlock
4978 all of the previous locks (X/Open spec). */
4979 if (i != num_locks && num_locks != 0) {
4981 * Ensure we don't do a remove on the lock that just failed,
4982 * as under POSIX rules, if we have a lock already there, we
4983 * will delete it (and we shouldn't) .....
4985 for(i--; i >= 0; i--) {
4986 lock_pid = get_lock_pid( data, i, large_file_format);
4987 count = get_lock_count( data, i, large_file_format);
4988 offset = get_lock_offset( data, i, large_file_format, &err);
4991 * There is no error code marked "stupid client bug".... :-).
4994 END_PROFILE(SMBlockingX);
4995 return ERROR_DOS(ERRDOS,ERRnoaccess);
4998 do_unlock(fsp,conn,lock_pid,count,offset);
5000 END_PROFILE(SMBlockingX);
5001 return ERROR_NT(status);
5004 set_message(outbuf,2,0,True);
5006 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5007 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5009 END_PROFILE(SMBlockingX);
5010 return chain_reply(inbuf,outbuf,length,bufsize);
5014 #define DBGC_CLASS DBGC_ALL
5016 /****************************************************************************
5017 Reply to a SMBreadbmpx (read block multiplex) request.
5018 ****************************************************************************/
5020 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5031 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5032 START_PROFILE(SMBreadBmpx);
5034 /* this function doesn't seem to work - disable by default */
5035 if (!lp_readbmpx()) {
5036 END_PROFILE(SMBreadBmpx);
5037 return ERROR_DOS(ERRSRV,ERRuseSTD);
5040 outsize = set_message(outbuf,8,0,True);
5042 CHECK_FSP(fsp,conn);
5045 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5046 maxcount = SVAL(inbuf,smb_vwv3);
5048 data = smb_buf(outbuf);
5049 pad = ((long)data)%4;
5054 max_per_packet = bufsize-(outsize+pad);
5058 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5059 END_PROFILE(SMBreadBmpx);
5060 return ERROR_DOS(ERRDOS,ERRlock);
5064 size_t N = MIN(max_per_packet,tcount-total_read);
5066 nread = read_file(fsp,data,startpos,N);
5071 if (nread < (ssize_t)N)
5072 tcount = total_read + nread;
5074 set_message(outbuf,8,nread,False);
5075 SIVAL(outbuf,smb_vwv0,startpos);
5076 SSVAL(outbuf,smb_vwv2,tcount);
5077 SSVAL(outbuf,smb_vwv6,nread);
5078 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5080 if (!send_smb(smbd_server_fd(),outbuf))
5081 exit_server("reply_readbmpx: send_smb failed.");
5083 total_read += nread;
5085 } while (total_read < (ssize_t)tcount);
5087 END_PROFILE(SMBreadBmpx);
5091 /****************************************************************************
5092 Reply to a SMBsetattrE.
5093 ****************************************************************************/
5095 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5097 struct utimbuf unix_times;
5099 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5100 START_PROFILE(SMBsetattrE);
5102 outsize = set_message(outbuf,0,0,True);
5104 if(!fsp || (fsp->conn != conn)) {
5105 END_PROFILE(SMBgetattrE);
5106 return ERROR_DOS(ERRDOS,ERRbadfid);
5110 * Convert the DOS times into unix times. Ignore create
5111 * time as UNIX can't set this.
5114 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5115 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5118 * Patch from Ray Frush <frush@engr.colostate.edu>
5119 * Sometimes times are sent as zero - ignore them.
5122 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5123 /* Ignore request */
5124 if( DEBUGLVL( 3 ) ) {
5125 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5126 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5128 END_PROFILE(SMBsetattrE);
5130 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5131 /* set modify time = to access time if modify time was unset */
5132 unix_times.modtime = unix_times.actime;
5135 /* Set the date on this file */
5136 /* Should we set pending modtime here ? JRA */
5137 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5138 END_PROFILE(SMBsetattrE);
5139 return ERROR_DOS(ERRDOS,ERRnoaccess);
5142 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5143 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5145 END_PROFILE(SMBsetattrE);
5150 /* Back from the dead for OS/2..... JRA. */
5152 /****************************************************************************
5153 Reply to a SMBwritebmpx (write block multiplex primary) request.
5154 ****************************************************************************/
5156 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5159 ssize_t nwritten = -1;
5166 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5167 START_PROFILE(SMBwriteBmpx);
5169 CHECK_FSP(fsp,conn);
5171 if (HAS_CACHED_ERROR(fsp)) {
5172 return(CACHED_ERROR(fsp));
5175 tcount = SVAL(inbuf,smb_vwv1);
5176 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5177 write_through = BITSETW(inbuf+smb_vwv7,0);
5178 numtowrite = SVAL(inbuf,smb_vwv10);
5179 smb_doff = SVAL(inbuf,smb_vwv11);
5181 data = smb_base(inbuf) + smb_doff;
5183 /* If this fails we need to send an SMBwriteC response,
5184 not an SMBwritebmpx - set this up now so we don't forget */
5185 SCVAL(outbuf,smb_com,SMBwritec);
5187 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5188 END_PROFILE(SMBwriteBmpx);
5189 return(ERROR_DOS(ERRDOS,ERRlock));
5192 nwritten = write_file(fsp,data,startpos,numtowrite);
5194 if(lp_syncalways(SNUM(conn)) || write_through)
5195 sync_file(conn,fsp);
5197 if(nwritten < (ssize_t)numtowrite) {
5198 END_PROFILE(SMBwriteBmpx);
5199 return(UNIXERROR(ERRHRD,ERRdiskfull));
5202 /* If the maximum to be written to this file
5203 is greater than what we just wrote then set
5204 up a secondary struct to be attached to this
5205 fd, we will use this to cache error messages etc. */
5207 if((ssize_t)tcount > nwritten) {
5208 write_bmpx_struct *wbms;
5209 if(fsp->wbmpx_ptr != NULL)
5210 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5212 wbms = SMB_MALLOC_P(write_bmpx_struct);
5214 DEBUG(0,("Out of memory in reply_readmpx\n"));
5215 END_PROFILE(SMBwriteBmpx);
5216 return(ERROR_DOS(ERRSRV,ERRnoresource));
5218 wbms->wr_mode = write_through;
5219 wbms->wr_discard = False; /* No errors yet */
5220 wbms->wr_total_written = nwritten;
5221 wbms->wr_errclass = 0;
5223 fsp->wbmpx_ptr = wbms;
5226 /* We are returning successfully, set the message type back to
5228 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5230 outsize = set_message(outbuf,1,0,True);
5232 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5234 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5235 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5237 if (write_through && tcount==nwritten) {
5238 /* We need to send both a primary and a secondary response */
5239 smb_setlen(outbuf,outsize - 4);
5240 if (!send_smb(smbd_server_fd(),outbuf))
5241 exit_server("reply_writebmpx: send_smb failed.");
5243 /* Now the secondary */
5244 outsize = set_message(outbuf,1,0,True);
5245 SCVAL(outbuf,smb_com,SMBwritec);
5246 SSVAL(outbuf,smb_vwv0,nwritten);
5249 END_PROFILE(SMBwriteBmpx);
5253 /****************************************************************************
5254 Reply to a SMBwritebs (write block multiplex secondary) request.
5255 ****************************************************************************/
5257 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5260 ssize_t nwritten = -1;
5267 write_bmpx_struct *wbms;
5268 BOOL send_response = False;
5269 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5270 START_PROFILE(SMBwriteBs);
5272 CHECK_FSP(fsp,conn);
5275 tcount = SVAL(inbuf,smb_vwv1);
5276 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5277 numtowrite = SVAL(inbuf,smb_vwv6);
5278 smb_doff = SVAL(inbuf,smb_vwv7);
5280 data = smb_base(inbuf) + smb_doff;
5282 /* We need to send an SMBwriteC response, not an SMBwritebs */
5283 SCVAL(outbuf,smb_com,SMBwritec);
5285 /* This fd should have an auxiliary struct attached,
5286 check that it does */
5287 wbms = fsp->wbmpx_ptr;
5289 END_PROFILE(SMBwriteBs);
5293 /* If write through is set we can return errors, else we must cache them */
5294 write_through = wbms->wr_mode;
5296 /* Check for an earlier error */
5297 if(wbms->wr_discard) {
5298 END_PROFILE(SMBwriteBs);
5299 return -1; /* Just discard the packet */
5302 nwritten = write_file(fsp,data,startpos,numtowrite);
5304 if(lp_syncalways(SNUM(conn)) || write_through)
5305 sync_file(conn,fsp);
5307 if (nwritten < (ssize_t)numtowrite) {
5309 /* We are returning an error - we can delete the aux struct */
5312 fsp->wbmpx_ptr = NULL;
5313 END_PROFILE(SMBwriteBs);
5314 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5316 wbms->wr_errclass = ERRHRD;
5317 wbms->wr_error = ERRdiskfull;
5318 wbms->wr_status = NT_STATUS_DISK_FULL;
5319 wbms->wr_discard = True;
5320 END_PROFILE(SMBwriteBs);
5324 /* Increment the total written, if this matches tcount
5325 we can discard the auxiliary struct (hurrah !) and return a writeC */
5326 wbms->wr_total_written += nwritten;
5327 if(wbms->wr_total_written >= tcount) {
5328 if (write_through) {
5329 outsize = set_message(outbuf,1,0,True);
5330 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5331 send_response = True;
5335 fsp->wbmpx_ptr = NULL;
5339 END_PROFILE(SMBwriteBs);
5343 END_PROFILE(SMBwriteBs);
5347 /****************************************************************************
5348 Reply to a SMBgetattrE.
5349 ****************************************************************************/
5351 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5353 SMB_STRUCT_STAT sbuf;
5356 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5357 START_PROFILE(SMBgetattrE);
5359 outsize = set_message(outbuf,11,0,True);
5361 if(!fsp || (fsp->conn != conn)) {
5362 END_PROFILE(SMBgetattrE);
5363 return ERROR_DOS(ERRDOS,ERRbadfid);
5366 /* Do an fstat on this file */
5367 if(fsp_stat(fsp, &sbuf)) {
5368 END_PROFILE(SMBgetattrE);
5369 return(UNIXERROR(ERRDOS,ERRnoaccess));
5372 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5375 * Convert the times into dos times. Set create
5376 * date to be last modify date as UNIX doesn't save
5380 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5381 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5382 /* Should we check pending modtime here ? JRA */
5383 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5386 SIVAL(outbuf,smb_vwv6,0);
5387 SIVAL(outbuf,smb_vwv8,0);
5389 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5390 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5391 SIVAL(outbuf,smb_vwv8,allocation_size);
5393 SSVAL(outbuf,smb_vwv10, mode);
5395 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5397 END_PROFILE(SMBgetattrE);