2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
33 extern char magic_char;
34 extern int global_oplock_break;
35 unsigned int smb_echo_count = 0;
36 extern uint32 global_client_caps;
38 extern BOOL global_encrypted_passwords_negotiated;
40 /****************************************************************************
41 Ensure we check the path in *exactly* the same way as W2K.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
50 const char *s = srcname;
51 NTSTATUS ret = NT_STATUS_OK;
52 BOOL start_of_name_component = True;
53 unsigned int num_bad_components = 0;
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
69 start_of_name_component = True;
73 if (start_of_name_component) {
74 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
75 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
78 * No mb char starts with '.' so we're safe checking the directory separator here.
81 /* If we just added a '/' - delete it */
82 if ((d > destname) && (*(d-1) == '/')) {
87 /* Are we at the start ? Can't go back further if so. */
89 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
92 /* Go back one level... */
93 /* We know this is safe as '/' cannot be part of a mb sequence. */
94 /* NOTE - if this assumption is invalid we are not in good shape... */
95 /* Decrement d first as d points to the *next* char to write into. */
96 for (d--; d > destname; d--) {
100 s += 2; /* Else go past the .. */
101 /* We're still at the start of a name component, just the previous one. */
103 if (num_bad_components) {
104 /* Hmmm. Should we only decrement the bad_components if
105 we're removing a bad component ? Need to check this. JRA. */
106 num_bad_components--;
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112 /* Component of pathname can't be "." only. */
113 ret = NT_STATUS_OBJECT_NAME_INVALID;
114 num_bad_components++;
121 if (allow_wcard_names) {
130 return NT_STATUS_OBJECT_NAME_INVALID;
137 switch(next_mb_char_size(s)) {
148 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
150 return NT_STATUS_INVALID_PARAMETER;
153 if (start_of_name_component && num_bad_components) {
154 num_bad_components++;
156 start_of_name_component = False;
159 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
160 /* For some strange reason being called from findfirst changes
161 the num_components number to cause the error return to change. JRA. */
162 if (allow_wcard_names) {
163 if (num_bad_components > 2) {
164 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
167 if (num_bad_components > 1) {
168 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
177 /****************************************************************************
178 Pull a string and check the path - provide for error return.
179 ****************************************************************************/
181 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)
184 char *tmppath_ptr = tmppath;
187 SMB_ASSERT(dest_len == sizeof(pstring));
191 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
193 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
195 *err = check_path_syntax(dest, tmppath, allow_wcard_names);
199 /****************************************************************************
200 Reply to a special message.
201 ****************************************************************************/
203 int reply_special(char *inbuf,char *outbuf)
206 int msg_type = CVAL(inbuf,0);
207 int msg_flags = CVAL(inbuf,1);
211 static BOOL already_got_session = False;
215 memset(outbuf,'\0',smb_size);
217 smb_setlen(outbuf,0);
220 case 0x81: /* session request */
222 if (already_got_session) {
223 exit_server("multiple session request not permitted");
226 SCVAL(outbuf,0,0x82);
228 if (name_len(inbuf+4) > 50 ||
229 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
230 DEBUG(0,("Invalid name length in session request\n"));
233 name_extract(inbuf,4,name1);
234 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
235 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
238 set_local_machine_name(name1, True);
239 set_remote_machine_name(name2, True);
241 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
242 get_local_machine_name(), get_remote_machine_name(),
245 if (name_type == 'R') {
246 /* We are being asked for a pathworks session ---
248 SCVAL(outbuf, 0,0x83);
252 /* only add the client's machine name to the list
253 of possibly valid usernames if we are operating
254 in share mode security */
255 if (lp_security() == SEC_SHARE) {
256 add_session_user(get_remote_machine_name());
259 reload_services(True);
262 already_got_session = True;
265 case 0x89: /* session keepalive request
266 (some old clients produce this?) */
267 SCVAL(outbuf,0,SMBkeepalive);
271 case 0x82: /* positive session response */
272 case 0x83: /* negative session response */
273 case 0x84: /* retarget session response */
274 DEBUG(0,("Unexpected session response\n"));
277 case SMBkeepalive: /* session keepalive */
282 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
283 msg_type, msg_flags));
288 /****************************************************************************
290 ****************************************************************************/
292 int reply_tcon(connection_struct *conn,
293 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
300 uint16 vuid = SVAL(inbuf,smb_uid);
304 DATA_BLOB password_blob;
306 START_PROFILE(SMBtcon);
308 *service_buf = *password = *dev = 0;
310 p = smb_buf(inbuf)+1;
311 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
312 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
314 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
316 p = strrchr_m(service_buf,'\\');
320 service = service_buf;
323 password_blob = data_blob(password, pwlen+1);
325 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
327 data_blob_clear_free(&password_blob);
330 END_PROFILE(SMBtcon);
331 return ERROR_NT(nt_status);
334 outsize = set_message(outbuf,2,0,True);
335 SSVAL(outbuf,smb_vwv0,max_recv);
336 SSVAL(outbuf,smb_vwv1,conn->cnum);
337 SSVAL(outbuf,smb_tid,conn->cnum);
339 DEBUG(3,("tcon service=%s cnum=%d\n",
340 service, conn->cnum));
342 END_PROFILE(SMBtcon);
346 /****************************************************************************
347 Reply to a tcon and X.
348 ****************************************************************************/
350 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
355 /* what the cleint thinks the device is */
356 fstring client_devicetype;
357 /* what the server tells the client the share represents */
358 const char *server_devicetype;
360 uint16 vuid = SVAL(inbuf,smb_uid);
361 int passlen = SVAL(inbuf,smb_vwv3);
364 extern BOOL global_encrypted_passwords_negotiated;
366 START_PROFILE(SMBtconX);
368 *service = *client_devicetype = 0;
370 /* we might have to close an old one */
371 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
372 close_cnum(conn,vuid);
375 if (passlen > MAX_PASS_LEN) {
376 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
379 if (global_encrypted_passwords_negotiated) {
380 password = data_blob(smb_buf(inbuf),passlen);
382 password = data_blob(smb_buf(inbuf),passlen+1);
383 /* Ensure correct termination */
384 password.data[passlen]=0;
387 p = smb_buf(inbuf) + passlen;
388 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
391 * the service name can be either: \\server\share
392 * or share directly like on the DELL PowerVault 705
395 q = strchr_m(path+2,'\\');
397 END_PROFILE(SMBtconX);
398 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
400 fstrcpy(service,q+1);
403 fstrcpy(service,path);
405 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
407 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
409 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
411 data_blob_clear_free(&password);
414 END_PROFILE(SMBtconX);
415 return ERROR_NT(nt_status);
419 server_devicetype = "IPC";
420 else if ( IS_PRINT(conn) )
421 server_devicetype = "LPT1:";
423 server_devicetype = "A:";
425 if (Protocol < PROTOCOL_NT1) {
426 set_message(outbuf,2,0,True);
428 p += srvstr_push(outbuf, p, server_devicetype, -1,
429 STR_TERMINATE|STR_ASCII);
430 set_message_end(outbuf,p);
432 /* NT sets the fstype of IPC$ to the null string */
433 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
435 set_message(outbuf,3,0,True);
438 p += srvstr_push(outbuf, p, server_devicetype, -1,
439 STR_TERMINATE|STR_ASCII);
440 p += srvstr_push(outbuf, p, fstype, -1,
443 set_message_end(outbuf,p);
445 /* what does setting this bit do? It is set by NT4 and
446 may affect the ability to autorun mounted cdroms */
447 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
448 (lp_csc_policy(SNUM(conn)) << 2));
450 init_dfsroot(conn, inbuf, outbuf);
454 DEBUG(3,("tconX service=%s \n",
457 /* set the incoming and outgoing tid to the just created one */
458 SSVAL(inbuf,smb_tid,conn->cnum);
459 SSVAL(outbuf,smb_tid,conn->cnum);
461 END_PROFILE(SMBtconX);
462 return chain_reply(inbuf,outbuf,length,bufsize);
465 /****************************************************************************
466 Reply to an unknown type.
467 ****************************************************************************/
469 int reply_unknown(char *inbuf,char *outbuf)
472 type = CVAL(inbuf,smb_com);
474 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
475 smb_fn_name(type), type, type));
477 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
480 /****************************************************************************
482 ****************************************************************************/
484 int reply_ioctl(connection_struct *conn,
485 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
487 uint16 device = SVAL(inbuf,smb_vwv1);
488 uint16 function = SVAL(inbuf,smb_vwv2);
489 uint32 ioctl_code = (device << 16) + function;
490 int replysize, outsize;
492 START_PROFILE(SMBioctl);
494 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
496 switch (ioctl_code) {
497 case IOCTL_QUERY_JOB_INFO:
501 END_PROFILE(SMBioctl);
502 return(ERROR_DOS(ERRSRV,ERRnosupport));
505 outsize = set_message(outbuf,8,replysize+1,True);
506 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
507 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
508 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
509 p = smb_buf(outbuf) + 1; /* Allow for alignment */
511 switch (ioctl_code) {
512 case IOCTL_QUERY_JOB_INFO:
514 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
516 END_PROFILE(SMBioctl);
517 return(UNIXERROR(ERRDOS,ERRbadfid));
519 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
520 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
522 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
528 END_PROFILE(SMBioctl);
532 /****************************************************************************
534 ****************************************************************************/
536 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
541 BOOL bad_path = False;
542 SMB_STRUCT_STAT sbuf;
545 START_PROFILE(SMBchkpth);
547 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
548 if (!NT_STATUS_IS_OK(status)) {
549 END_PROFILE(SMBchkpth);
550 return ERROR_NT(status);
553 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
555 unix_convert(name,conn,0,&bad_path,&sbuf);
557 END_PROFILE(SMBchkpth);
558 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
561 if (check_name(name,conn)) {
562 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
563 if (!(ok = S_ISDIR(sbuf.st_mode))) {
564 END_PROFILE(SMBchkpth);
565 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
570 /* We special case this - as when a Windows machine
571 is parsing a path is steps through the components
572 one at a time - if a component fails it expects
573 ERRbadpath, not ERRbadfile.
575 if(errno == ENOENT) {
577 * Windows returns different error codes if
578 * the parent directory is valid but not the
579 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
580 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
581 * if the path is invalid. This is different from set_bad_path_error()
582 * in the non-NT error case.
584 END_PROFILE(SMBchkpth);
585 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
588 END_PROFILE(SMBchkpth);
589 return(UNIXERROR(ERRDOS,ERRbadpath));
592 outsize = set_message(outbuf,0,0,True);
593 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
595 END_PROFILE(SMBchkpth);
599 /****************************************************************************
601 ****************************************************************************/
603 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
607 SMB_STRUCT_STAT sbuf;
612 BOOL bad_path = False;
616 START_PROFILE(SMBgetatr);
618 p = smb_buf(inbuf) + 1;
619 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
620 if (!NT_STATUS_IS_OK(status)) {
621 END_PROFILE(SMBgetatr);
622 return ERROR_NT(status);
625 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
627 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
628 under WfWg - weird! */
630 mode = aHIDDEN | aDIR;
631 if (!CAN_WRITE(conn))
637 unix_convert(fname,conn,0,&bad_path,&sbuf);
639 END_PROFILE(SMBgetatr);
640 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
642 if (check_name(fname,conn)) {
643 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
644 mode = dos_mode(conn,fname,&sbuf);
646 mtime = sbuf.st_mtime;
651 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
657 END_PROFILE(SMBgetatr);
658 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
661 outsize = set_message(outbuf,10,0,True);
663 SSVAL(outbuf,smb_vwv0,mode);
664 if(lp_dos_filetime_resolution(SNUM(conn)) )
665 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
667 put_dos_date3(outbuf,smb_vwv1,mtime);
668 SIVAL(outbuf,smb_vwv3,(uint32)size);
670 if (Protocol >= PROTOCOL_NT1)
671 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
673 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
675 END_PROFILE(SMBgetatr);
679 /****************************************************************************
681 ****************************************************************************/
683 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
690 SMB_STRUCT_STAT sbuf;
691 BOOL bad_path = False;
695 START_PROFILE(SMBsetatr);
697 p = smb_buf(inbuf) + 1;
698 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
699 if (!NT_STATUS_IS_OK(status)) {
700 END_PROFILE(SMBsetatr);
701 return ERROR_NT(status);
704 unix_convert(fname,conn,0,&bad_path,&sbuf);
706 END_PROFILE(SMBsetatr);
707 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
710 mode = SVAL(inbuf,smb_vwv0);
711 mtime = make_unix_date3(inbuf+smb_vwv1);
713 if (mode != FILE_ATTRIBUTE_NORMAL) {
714 if (VALID_STAT_OF_DIR(sbuf))
719 if (check_name(fname,conn)) {
720 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
727 ok = set_filetime(conn,fname,mtime);
730 END_PROFILE(SMBsetatr);
731 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
734 outsize = set_message(outbuf,0,0,True);
736 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
738 END_PROFILE(SMBsetatr);
742 /****************************************************************************
744 ****************************************************************************/
746 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
749 SMB_BIG_UINT dfree,dsize,bsize;
750 START_PROFILE(SMBdskattr);
752 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
754 outsize = set_message(outbuf,5,0,True);
756 if (Protocol <= PROTOCOL_LANMAN2) {
757 double total_space, free_space;
758 /* we need to scale this to a number that DOS6 can handle. We
759 use floating point so we can handle large drives on systems
760 that don't have 64 bit integers
762 we end up displaying a maximum of 2G to DOS systems
764 total_space = dsize * (double)bsize;
765 free_space = dfree * (double)bsize;
767 dsize = (total_space+63*512) / (64*512);
768 dfree = (free_space+63*512) / (64*512);
770 if (dsize > 0xFFFF) dsize = 0xFFFF;
771 if (dfree > 0xFFFF) dfree = 0xFFFF;
773 SSVAL(outbuf,smb_vwv0,dsize);
774 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
775 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
776 SSVAL(outbuf,smb_vwv3,dfree);
778 SSVAL(outbuf,smb_vwv0,dsize);
779 SSVAL(outbuf,smb_vwv1,bsize/512);
780 SSVAL(outbuf,smb_vwv2,512);
781 SSVAL(outbuf,smb_vwv3,dfree);
784 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
786 END_PROFILE(SMBdskattr);
790 /****************************************************************************
792 Can be called from SMBsearch, SMBffirst or SMBfunique.
793 ****************************************************************************/
795 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
805 unsigned int numentries = 0;
806 unsigned int maxentries = 0;
807 BOOL finished = False;
814 BOOL check_descend = False;
815 BOOL expect_close = False;
816 BOOL can_open = True;
817 BOOL bad_path = False;
819 START_PROFILE(SMBsearch);
821 *mask = *directory = *fname = 0;
823 /* If we were called as SMBffirst then we must expect close. */
824 if(CVAL(inbuf,smb_com) == SMBffirst)
827 outsize = set_message(outbuf,1,3,True);
828 maxentries = SVAL(inbuf,smb_vwv0);
829 dirtype = SVAL(inbuf,smb_vwv1);
830 p = smb_buf(inbuf) + 1;
831 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
832 if (!NT_STATUS_IS_OK(nt_status)) {
833 END_PROFILE(SMBsearch);
834 return ERROR_NT(nt_status);
837 status_len = SVAL(p, 0);
840 /* dirtype &= ~aDIR; */
842 if (status_len == 0) {
843 SMB_STRUCT_STAT sbuf;
846 pstrcpy(directory,path);
848 unix_convert(directory,conn,0,&bad_path,&sbuf);
851 if (!check_name(directory,conn))
854 p = strrchr_m(dir2,'/');
863 p = strrchr_m(directory,'/');
869 if (strlen(directory) == 0)
870 pstrcpy(directory,".");
871 memset((char *)status,'\0',21);
872 SCVAL(status,0,(dirtype & 0x1F));
877 status_dirtype = CVAL(status,0) & 0x1F;
878 if (status_dirtype != (dirtype & 0x1F))
879 dirtype = status_dirtype;
881 conn->dirptr = dptr_fetch(status+12,&dptr_num);
884 string_set(&conn->dirpath,dptr_path(dptr_num));
885 pstrcpy(mask, dptr_wcard(dptr_num));
889 p = smb_buf(outbuf) + 3;
892 if (status_len == 0) {
893 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
896 END_PROFILE(SMBsearch);
897 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
899 END_PROFILE(SMBsearch);
900 return ERROR_DOS(ERRDOS,ERRnofids);
902 dptr_set_wcard(dptr_num, SMB_STRDUP(mask));
903 dptr_set_attr(dptr_num, dirtype);
905 dirtype = dptr_attr(dptr_num);
908 DEBUG(4,("dptr_num is %d\n",dptr_num));
911 if ((dirtype&0x1F) == aVOLID) {
913 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
914 dptr_fill(p+12,dptr_num);
915 if (dptr_zero(p+12) && (status_len==0))
919 p += DIR_STRUCT_SIZE;
922 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
924 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
925 conn->dirpath,lp_dontdescend(SNUM(conn))));
926 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
927 check_descend = True;
929 for (i=numentries;(i<maxentries) && !finished;i++) {
930 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
933 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
934 dptr_fill(p+12,dptr_num);
936 p += DIR_STRUCT_SIZE;
946 /* If we were called as SMBffirst with smb_search_id == NULL
947 and no entries were found then return error and close dirptr
950 if(ok && expect_close && numentries == 0 && status_len == 0) {
951 /* Close the dptr - we know it's gone */
952 dptr_close(&dptr_num);
953 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
954 } else if (numentries == 0 || !ok) {
955 dptr_close(&dptr_num);
956 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
959 /* If we were called as SMBfunique, then we can close the dirptr now ! */
960 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
961 dptr_close(&dptr_num);
963 SSVAL(outbuf,smb_vwv0,numentries);
964 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
965 SCVAL(smb_buf(outbuf),0,5);
966 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
968 if (Protocol >= PROTOCOL_NT1)
969 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
971 outsize += DIR_STRUCT_SIZE*numentries;
972 smb_setlen(outbuf,outsize - 4);
974 if ((! *directory) && dptr_path(dptr_num))
975 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
977 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
978 smb_fn_name(CVAL(inbuf,smb_com)),
979 mask, directory, dirtype, numentries, maxentries ) );
981 END_PROFILE(SMBsearch);
985 /****************************************************************************
986 Reply to a fclose (stop directory search).
987 ****************************************************************************/
989 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
999 START_PROFILE(SMBfclose);
1001 outsize = set_message(outbuf,1,0,True);
1002 p = smb_buf(inbuf) + 1;
1003 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1004 if (!NT_STATUS_IS_OK(err)) {
1005 END_PROFILE(SMBfclose);
1006 return ERROR_NT(err);
1009 status_len = SVAL(p,0);
1012 if (status_len == 0) {
1013 END_PROFILE(SMBfclose);
1014 return ERROR_DOS(ERRSRV,ERRsrverror);
1017 memcpy(status,p,21);
1019 if(dptr_fetch(status+12,&dptr_num)) {
1020 /* Close the dptr - we know it's gone */
1021 dptr_close(&dptr_num);
1024 SSVAL(outbuf,smb_vwv0,0);
1026 DEBUG(3,("search close\n"));
1028 END_PROFILE(SMBfclose);
1032 /****************************************************************************
1034 ****************************************************************************/
1036 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1045 SMB_STRUCT_STAT sbuf;
1046 BOOL bad_path = False;
1048 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1049 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1051 START_PROFILE(SMBopen);
1053 share_mode = SVAL(inbuf,smb_vwv0);
1055 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1056 if (!NT_STATUS_IS_OK(status)) {
1057 END_PROFILE(SMBopen);
1058 return ERROR_NT(status);
1061 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1063 unix_convert(fname,conn,0,&bad_path,&sbuf);
1065 END_PROFILE(SMBopen);
1066 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1069 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1070 (uint32)dos_attr, oplock_request,&rmode,NULL);
1073 END_PROFILE(SMBopen);
1074 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1075 /* We have re-scheduled this call. */
1076 clear_cached_errors();
1079 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1082 size = sbuf.st_size;
1083 fmode = dos_mode(conn,fname,&sbuf);
1084 mtime = sbuf.st_mtime;
1087 DEBUG(3,("attempt to open a directory %s\n",fname));
1088 close_file(fsp,False);
1089 END_PROFILE(SMBopen);
1090 return ERROR_DOS(ERRDOS,ERRnoaccess);
1093 outsize = set_message(outbuf,7,0,True);
1094 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1095 SSVAL(outbuf,smb_vwv1,fmode);
1096 if(lp_dos_filetime_resolution(SNUM(conn)) )
1097 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1099 put_dos_date3(outbuf,smb_vwv2,mtime);
1100 SIVAL(outbuf,smb_vwv4,(uint32)size);
1101 SSVAL(outbuf,smb_vwv6,rmode);
1103 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1104 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1106 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1107 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1108 END_PROFILE(SMBopen);
1112 /****************************************************************************
1113 Reply to an open and X.
1114 ****************************************************************************/
1116 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1119 int smb_mode = SVAL(inbuf,smb_vwv3);
1120 int smb_attr = SVAL(inbuf,smb_vwv5);
1121 /* Breakout the oplock request bits so we can set the
1122 reply bits separately. */
1123 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1124 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1125 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1127 int open_flags = SVAL(inbuf,smb_vwv2);
1128 int smb_sattr = SVAL(inbuf,smb_vwv4);
1129 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1131 int smb_ofun = SVAL(inbuf,smb_vwv8);
1133 int fmode=0,mtime=0,rmode=0;
1134 SMB_STRUCT_STAT sbuf;
1136 BOOL bad_path = False;
1139 START_PROFILE(SMBopenX);
1141 /* If it's an IPC, pass off the pipe handler. */
1143 if (lp_nt_pipe_support()) {
1144 END_PROFILE(SMBopenX);
1145 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1147 END_PROFILE(SMBopenX);
1148 return ERROR_DOS(ERRSRV,ERRaccess);
1152 /* XXXX we need to handle passed times, sattr and flags */
1153 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1154 if (!NT_STATUS_IS_OK(status)) {
1155 END_PROFILE(SMBopenX);
1156 return ERROR_NT(status);
1159 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1161 unix_convert(fname,conn,0,&bad_path,&sbuf);
1163 END_PROFILE(SMBopenX);
1164 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1167 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1168 oplock_request, &rmode,&smb_action);
1171 END_PROFILE(SMBopenX);
1172 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1173 /* We have re-scheduled this call. */
1174 clear_cached_errors();
1177 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1180 size = sbuf.st_size;
1181 fmode = dos_mode(conn,fname,&sbuf);
1182 mtime = sbuf.st_mtime;
1184 close_file(fsp,False);
1185 END_PROFILE(SMBopenX);
1186 return ERROR_DOS(ERRDOS,ERRnoaccess);
1189 /* If the caller set the extended oplock request bit
1190 and we granted one (by whatever means) - set the
1191 correct bit for extended oplock reply.
1194 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1195 smb_action |= EXTENDED_OPLOCK_GRANTED;
1197 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1198 smb_action |= EXTENDED_OPLOCK_GRANTED;
1200 /* If the caller set the core oplock request bit
1201 and we granted one (by whatever means) - set the
1202 correct bit for core oplock reply.
1205 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1206 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1208 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1209 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1211 set_message(outbuf,15,0,True);
1212 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1213 SSVAL(outbuf,smb_vwv3,fmode);
1214 if(lp_dos_filetime_resolution(SNUM(conn)) )
1215 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1217 put_dos_date3(outbuf,smb_vwv4,mtime);
1218 SIVAL(outbuf,smb_vwv6,(uint32)size);
1219 SSVAL(outbuf,smb_vwv8,rmode);
1220 SSVAL(outbuf,smb_vwv11,smb_action);
1222 END_PROFILE(SMBopenX);
1223 return chain_reply(inbuf,outbuf,length,bufsize);
1226 /****************************************************************************
1227 Reply to a SMBulogoffX.
1228 ****************************************************************************/
1230 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1232 uint16 vuid = SVAL(inbuf,smb_uid);
1233 user_struct *vuser = get_valid_user_struct(vuid);
1234 START_PROFILE(SMBulogoffX);
1237 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1239 /* in user level security we are supposed to close any files
1240 open by this user */
1241 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1242 file_close_user(vuid);
1244 invalidate_vuid(vuid);
1246 set_message(outbuf,2,0,True);
1248 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1250 END_PROFILE(SMBulogoffX);
1251 return chain_reply(inbuf,outbuf,length,bufsize);
1254 /****************************************************************************
1255 Reply to a mknew or a create.
1256 ****************************************************************************/
1258 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1265 BOOL bad_path = False;
1267 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1268 SMB_STRUCT_STAT sbuf;
1270 START_PROFILE(SMBcreate);
1272 com = SVAL(inbuf,smb_com);
1274 createmode = SVAL(inbuf,smb_vwv0);
1275 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 END_PROFILE(SMBcreate);
1278 return ERROR_NT(status);
1281 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1283 unix_convert(fname,conn,0,&bad_path,&sbuf);
1285 END_PROFILE(SMBcreate);
1286 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1289 if (createmode & aVOLID)
1290 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1292 if(com == SMBmknew) {
1293 /* We should fail if file exists. */
1294 ofun = FILE_CREATE_IF_NOT_EXIST;
1296 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1297 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1300 /* Open file in dos compatibility share mode. */
1301 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1302 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1305 END_PROFILE(SMBcreate);
1306 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1307 /* We have re-scheduled this call. */
1308 clear_cached_errors();
1311 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1314 outsize = set_message(outbuf,1,0,True);
1315 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1317 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1318 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1320 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1321 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1323 DEBUG( 2, ( "new file %s\n", fname ) );
1324 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1326 END_PROFILE(SMBcreate);
1330 /****************************************************************************
1331 Reply to a create temporary file.
1332 ****************************************************************************/
1334 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1339 BOOL bad_path = False;
1341 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1343 SMB_STRUCT_STAT sbuf;
1346 unsigned int namelen;
1348 START_PROFILE(SMBctemp);
1350 createattr = SVAL(inbuf,smb_vwv0);
1351 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 END_PROFILE(SMBctemp);
1354 return ERROR_NT(status);
1357 pstrcat(fname,"/TMXXXXXX");
1359 pstrcat(fname,"TMXXXXXX");
1362 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1364 unix_convert(fname,conn,0,&bad_path,&sbuf);
1366 END_PROFILE(SMBctemp);
1367 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1370 tmpfd = smb_mkstemp(fname);
1372 END_PROFILE(SMBctemp);
1373 return(UNIXERROR(ERRDOS,ERRnoaccess));
1376 SMB_VFS_STAT(conn,fname,&sbuf);
1378 /* Open file in dos compatibility share mode. */
1379 /* We should fail if file does not exist. */
1380 fsp = open_file_shared(conn,fname,&sbuf,
1381 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1382 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1383 (uint32)createattr, oplock_request, NULL, NULL);
1385 /* close fd from smb_mkstemp() */
1389 END_PROFILE(SMBctemp);
1390 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1391 /* We have re-scheduled this call. */
1392 clear_cached_errors();
1395 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1398 outsize = set_message(outbuf,1,0,True);
1399 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1401 /* the returned filename is relative to the directory */
1402 s = strrchr_m(fname, '/');
1408 p = smb_buf(outbuf);
1410 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1411 thing in the byte section. JRA */
1412 SSVALS(p, 0, -1); /* what is this? not in spec */
1414 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1416 outsize = set_message_end(outbuf, p);
1418 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1419 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1421 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1422 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1424 DEBUG( 2, ( "created temp file %s\n", fname ) );
1425 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1426 fname, fsp->fd, sbuf.st_mode ) );
1428 END_PROFILE(SMBctemp);
1432 /*******************************************************************
1433 Check if a user is allowed to rename a file.
1434 ********************************************************************/
1436 static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
1443 if (!CAN_WRITE(conn))
1444 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1446 fmode = dos_mode(conn,fname,pst);
1447 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1448 return NT_STATUS_NO_SUCH_FILE;
1450 if (S_ISDIR(pst->st_mode))
1451 return NT_STATUS_OK;
1453 /* We need a better way to return NT status codes from open... */
1457 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1458 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1461 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1462 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1463 ret = NT_STATUS_SHARING_VIOLATION;
1466 unix_ERR_ntstatus = NT_STATUS_OK;
1469 close_file(fsp,False);
1470 return NT_STATUS_OK;
1473 /*******************************************************************
1474 Check if a user is allowed to delete a file.
1475 ********************************************************************/
1477 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1479 SMB_STRUCT_STAT sbuf;
1485 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1488 if (!CAN_WRITE(conn))
1489 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1491 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1492 if(errno == ENOENT) {
1494 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1496 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1498 return map_nt_error_from_unix(errno);
1501 fmode = dos_mode(conn,fname,&sbuf);
1503 /* Can't delete a directory. */
1505 return NT_STATUS_FILE_IS_A_DIRECTORY;
1507 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1508 return NT_STATUS_OBJECT_NAME_INVALID;
1509 #endif /* JRATEST */
1511 if (!lp_delete_readonly(SNUM(conn))) {
1513 return NT_STATUS_CANNOT_DELETE;
1515 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1516 return NT_STATUS_NO_SUCH_FILE;
1518 /* We need a better way to return NT status codes from open... */
1522 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1523 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1526 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1527 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1528 ret = unix_ERR_ntstatus;
1529 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1530 ret = NT_STATUS_SHARING_VIOLATION;
1533 unix_ERR_ntstatus = NT_STATUS_OK;
1536 close_file(fsp,False);
1537 return NT_STATUS_OK;
1540 /****************************************************************************
1541 The guts of the unlink command, split out so it may be called by the NT SMB
1543 ****************************************************************************/
1545 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1551 NTSTATUS error = NT_STATUS_OK;
1553 BOOL bad_path = False;
1555 SMB_STRUCT_STAT sbuf;
1557 *directory = *mask = 0;
1559 /* We must check for wildcards in the name given
1560 * directly by the client - before any unmangling.
1561 * This prevents an unmangling of a UNIX name containing
1562 * a DOS wildcard like '*' or '?' from unmangling into
1563 * a wildcard delete which was not intended.
1564 * FIX for #226. JRA.
1567 has_wild = ms_has_wild(name);
1569 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1571 p = strrchr_m(name,'/');
1573 pstrcpy(directory,".");
1577 pstrcpy(directory,name);
1582 * We should only check the mangled cache
1583 * here if unix_convert failed. This means
1584 * that the path in 'mask' doesn't exist
1585 * on the file system and so we need to look
1586 * for a possible mangle. This patch from
1587 * Tine Smukavec <valentin.smukavec@hermes.si>.
1590 if (!rc && mangle_is_mangled(mask))
1591 mangle_check_cache( mask, sizeof(pstring)-1 );
1594 pstrcat(directory,"/");
1595 pstrcat(directory,mask);
1596 error = can_delete(directory,conn,dirtype,bad_path);
1597 if (!NT_STATUS_IS_OK(error))
1600 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1604 void *dirptr = NULL;
1607 if (check_name(directory,conn))
1608 dirptr = OpenDir(conn, directory, True);
1610 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1611 the pattern matches against the long name, otherwise the short name
1612 We don't implement this yet XXXX
1616 error = NT_STATUS_NO_SUCH_FILE;
1618 if (strequal(mask,"????????.???"))
1621 while ((dname = ReadDirName(dirptr))) {
1623 BOOL sys_direntry = False;
1624 pstrcpy(fname,dname);
1626 /* Quick check for "." and ".." */
1627 if (fname[0] == '.') {
1628 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1629 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1630 sys_direntry = True;
1637 if(!mask_match(fname, mask, conn->case_sensitive))
1641 error = NT_STATUS_OBJECT_NAME_INVALID;
1642 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1647 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1648 error = can_delete(fname,conn,dirtype,bad_path);
1649 if (!NT_STATUS_IS_OK(error)) {
1652 if (SMB_VFS_UNLINK(conn,fname) == 0)
1654 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1660 if (count == 0 && NT_STATUS_IS_OK(error)) {
1661 error = map_nt_error_from_unix(errno);
1667 /****************************************************************************
1669 ****************************************************************************/
1671 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1678 START_PROFILE(SMBunlink);
1680 dirtype = SVAL(inbuf,smb_vwv0);
1682 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 END_PROFILE(SMBunlink);
1685 return ERROR_NT(status);
1688 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1690 DEBUG(3,("reply_unlink : %s\n",name));
1692 status = unlink_internals(conn, dirtype, name);
1693 if (!NT_STATUS_IS_OK(status)) {
1694 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1695 /* We have re-scheduled this call. */
1696 clear_cached_errors();
1699 return ERROR_NT(status);
1703 * Win2k needs a changenotify request response before it will
1704 * update after a rename..
1706 process_pending_change_notify_queue((time_t)0);
1708 outsize = set_message(outbuf,0,0,True);
1710 END_PROFILE(SMBunlink);
1714 /****************************************************************************
1716 ****************************************************************************/
1718 static void fail_readraw(void)
1721 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1723 exit_server(errstr);
1726 #if defined(WITH_SENDFILE)
1727 /****************************************************************************
1728 Fake (read/write) sendfile. Returns -1 on read or write fail.
1729 ****************************************************************************/
1731 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1735 /* Paranioa check... */
1736 if (nread > bufsize) {
1741 ret = read_file(fsp,buf,startpos,nread);
1747 /* If we had a short read, fill with zeros. */
1749 memset(buf, '\0', nread - ret);
1752 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1756 return (ssize_t)nread;
1760 /****************************************************************************
1761 Use sendfile in readbraw.
1762 ****************************************************************************/
1764 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1765 ssize_t mincount, char *outbuf, int out_buffsize)
1769 #if defined(WITH_SENDFILE)
1771 * We can only use sendfile on a non-chained packet
1772 * but we can use on a non-oplocked file. tridge proved this
1773 * on a train in Germany :-). JRA.
1774 * reply_readbraw has already checked the length.
1777 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1780 _smb_setlen(outbuf,nread);
1781 header.data = outbuf;
1785 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1787 * Special hack for broken Linux with no working sendfile. If we
1788 * return EINTR we sent the header but not the rest of the data.
1789 * Fake this up by doing read/write calls.
1791 if (errno == EINTR) {
1792 /* Ensure we don't do this again. */
1793 set_use_sendfile(SNUM(conn), False);
1794 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1796 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1797 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1798 fsp->fsp_name, strerror(errno) ));
1799 exit_server("send_file_readbraw fake_sendfile failed");
1804 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1805 fsp->fsp_name, strerror(errno) ));
1806 exit_server("send_file_readbraw sendfile failed");
1814 ret = read_file(fsp,outbuf+4,startpos,nread);
1815 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1824 _smb_setlen(outbuf,ret);
1825 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1829 /****************************************************************************
1830 Reply to a readbraw (core+ protocol).
1831 ****************************************************************************/
1833 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1835 extern struct current_user current_user;
1836 ssize_t maxcount,mincount;
1839 char *header = outbuf;
1841 START_PROFILE(SMBreadbraw);
1843 if (srv_is_signing_active()) {
1844 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1848 * Special check if an oplock break has been issued
1849 * and the readraw request croses on the wire, we must
1850 * return a zero length response here.
1853 if(global_oplock_break) {
1854 _smb_setlen(header,0);
1855 if (write_data(smbd_server_fd(),header,4) != 4)
1857 DEBUG(5,("readbraw - oplock break finished\n"));
1858 END_PROFILE(SMBreadbraw);
1862 fsp = file_fsp(inbuf,smb_vwv0);
1864 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1866 * fsp could be NULL here so use the value from the packet. JRA.
1868 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1869 _smb_setlen(header,0);
1870 if (write_data(smbd_server_fd(),header,4) != 4)
1872 END_PROFILE(SMBreadbraw);
1876 CHECK_FSP(fsp,conn);
1878 flush_write_cache(fsp, READRAW_FLUSH);
1880 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1881 if(CVAL(inbuf,smb_wct) == 10) {
1883 * This is a large offset (64 bit) read.
1885 #ifdef LARGE_SMB_OFF_T
1887 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1889 #else /* !LARGE_SMB_OFF_T */
1892 * Ensure we haven't been sent a >32 bit offset.
1895 if(IVAL(inbuf,smb_vwv8) != 0) {
1896 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1897 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1898 _smb_setlen(header,0);
1899 if (write_data(smbd_server_fd(),header,4) != 4)
1901 END_PROFILE(SMBreadbraw);
1905 #endif /* LARGE_SMB_OFF_T */
1908 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1909 _smb_setlen(header,0);
1910 if (write_data(smbd_server_fd(),header,4) != 4)
1912 END_PROFILE(SMBreadbraw);
1916 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1917 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1919 /* ensure we don't overrun the packet size */
1920 maxcount = MIN(65535,maxcount);
1922 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1923 SMB_OFF_T size = fsp->size;
1924 SMB_OFF_T sizeneeded = startpos + maxcount;
1926 if (size < sizeneeded) {
1928 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1930 if (!fsp->can_write)
1934 if (startpos >= size)
1937 nread = MIN(maxcount,(size - startpos));
1940 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1941 if (nread < mincount)
1945 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1946 (int)maxcount, (int)mincount, (int)nread ) );
1948 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
1950 DEBUG(5,("readbraw finished\n"));
1951 END_PROFILE(SMBreadbraw);
1955 /****************************************************************************
1956 Reply to a lockread (core+ protocol).
1957 ****************************************************************************/
1959 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1967 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1968 BOOL my_lock_ctx = False;
1969 START_PROFILE(SMBlockread);
1971 CHECK_FSP(fsp,conn);
1974 release_level_2_oplocks_on_change(fsp);
1976 numtoread = SVAL(inbuf,smb_vwv1);
1977 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1979 outsize = set_message(outbuf,5,3,True);
1980 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1981 data = smb_buf(outbuf) + 3;
1984 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1985 * protocol request that predates the read/write lock concept.
1986 * Thus instead of asking for a read lock here we need to ask
1987 * for a write lock. JRA.
1988 * Note that the requested lock size is unaffected by max_recv.
1991 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1992 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1994 if (NT_STATUS_V(status)) {
1997 * We used to make lockread a blocking lock. It turns out
1998 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2002 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2004 * A blocking lock was requested. Package up
2005 * this smb into a queued request and push it
2006 * onto the blocking lock queue.
2008 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2009 (SMB_BIG_UINT)numtoread)) {
2010 END_PROFILE(SMBlockread);
2015 END_PROFILE(SMBlockread);
2016 return ERROR_NT(status);
2020 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2023 if (numtoread > max_recv) {
2024 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2025 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2026 (unsigned int)numtoread, (unsigned int)max_recv ));
2027 numtoread = MIN(numtoread,max_recv);
2029 nread = read_file(fsp,data,startpos,numtoread);
2032 END_PROFILE(SMBlockread);
2033 return(UNIXERROR(ERRDOS,ERRnoaccess));
2037 SSVAL(outbuf,smb_vwv0,nread);
2038 SSVAL(outbuf,smb_vwv5,nread+3);
2039 SSVAL(smb_buf(outbuf),1,nread);
2041 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2042 fsp->fnum, (int)numtoread, (int)nread));
2044 END_PROFILE(SMBlockread);
2048 /****************************************************************************
2050 ****************************************************************************/
2052 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2059 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2060 START_PROFILE(SMBread);
2062 CHECK_FSP(fsp,conn);
2065 numtoread = SVAL(inbuf,smb_vwv1);
2066 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2068 outsize = set_message(outbuf,5,3,True);
2069 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2071 * The requested read size cannot be greater than max_recv. JRA.
2073 if (numtoread > max_recv) {
2074 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2075 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2076 (unsigned int)numtoread, (unsigned int)max_recv ));
2077 numtoread = MIN(numtoread,max_recv);
2080 data = smb_buf(outbuf) + 3;
2082 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2083 END_PROFILE(SMBread);
2084 return ERROR_DOS(ERRDOS,ERRlock);
2088 nread = read_file(fsp,data,startpos,numtoread);
2091 END_PROFILE(SMBread);
2092 return(UNIXERROR(ERRDOS,ERRnoaccess));
2096 SSVAL(outbuf,smb_vwv0,nread);
2097 SSVAL(outbuf,smb_vwv5,nread+3);
2098 SCVAL(smb_buf(outbuf),0,1);
2099 SSVAL(smb_buf(outbuf),1,nread);
2101 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2102 fsp->fnum, (int)numtoread, (int)nread ) );
2104 END_PROFILE(SMBread);
2108 /****************************************************************************
2109 Reply to a read and X - possibly using sendfile.
2110 ****************************************************************************/
2112 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2113 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2116 char *data = smb_buf(outbuf);
2118 #if defined(WITH_SENDFILE)
2120 * We can only use sendfile on a non-chained packet
2121 * but we can use on a non-oplocked file. tridge proved this
2122 * on a train in Germany :-). JRA.
2125 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2126 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2127 SMB_STRUCT_STAT sbuf;
2130 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2131 return(UNIXERROR(ERRDOS,ERRnoaccess));
2133 if (startpos > sbuf.st_size)
2136 if (smb_maxcnt > (sbuf.st_size - startpos))
2137 smb_maxcnt = (sbuf.st_size - startpos);
2139 if (smb_maxcnt == 0)
2143 * Set up the packet header before send. We
2144 * assume here the sendfile will work (get the
2145 * correct amount of data).
2148 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2149 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2150 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2151 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2152 SCVAL(outbuf,smb_vwv0,0xFF);
2153 set_message(outbuf,12,smb_maxcnt,False);
2154 header.data = outbuf;
2155 header.length = data - outbuf;
2158 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2160 * Special hack for broken Linux with no working sendfile. If we
2161 * return EINTR we sent the header but not the rest of the data.
2162 * Fake this up by doing read/write calls.
2164 if (errno == EINTR) {
2165 /* Ensure we don't do this again. */
2166 set_use_sendfile(SNUM(conn), False);
2167 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2169 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2170 len_outbuf - (data-outbuf))) == -1) {
2171 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2172 fsp->fsp_name, strerror(errno) ));
2173 exit_server("send_file_readX: fake_sendfile failed");
2178 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2179 fsp->fsp_name, strerror(errno) ));
2180 exit_server("send_file_readX sendfile failed");
2183 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2184 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2192 nread = read_file(fsp,data,startpos,smb_maxcnt);
2195 END_PROFILE(SMBreadX);
2196 return(UNIXERROR(ERRDOS,ERRnoaccess));
2199 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2200 SSVAL(outbuf,smb_vwv5,nread);
2201 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2202 SSVAL(smb_buf(outbuf),-2,nread);
2204 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2205 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2210 /****************************************************************************
2211 Reply to a read and X.
2212 ****************************************************************************/
2214 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2216 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2217 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2219 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2221 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2224 START_PROFILE(SMBreadX);
2226 /* If it's an IPC, pass off the pipe handler. */
2228 END_PROFILE(SMBreadX);
2229 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2232 CHECK_FSP(fsp,conn);
2235 set_message(outbuf,12,0,True);
2237 if (global_client_caps & CAP_LARGE_READX) {
2238 smb_maxcnt |= ((((size_t)SVAL(inbuf,smb_vwv7)) & 1 )<<16);
2239 if (smb_maxcnt > BUFFER_SIZE) {
2240 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2241 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2242 END_PROFILE(SMBreadX);
2243 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2247 if(CVAL(inbuf,smb_wct) == 12) {
2248 #ifdef LARGE_SMB_OFF_T
2250 * This is a large offset (64 bit) read.
2252 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2254 #else /* !LARGE_SMB_OFF_T */
2257 * Ensure we haven't been sent a >32 bit offset.
2260 if(IVAL(inbuf,smb_vwv10) != 0) {
2261 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2262 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2263 END_PROFILE(SMBreadX);
2264 return ERROR_DOS(ERRDOS,ERRbadaccess);
2267 #endif /* LARGE_SMB_OFF_T */
2271 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2272 END_PROFILE(SMBreadX);
2273 return ERROR_DOS(ERRDOS,ERRlock);
2276 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2278 nread = chain_reply(inbuf,outbuf,length,bufsize);
2280 END_PROFILE(SMBreadX);
2284 /****************************************************************************
2285 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2286 ****************************************************************************/
2288 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2291 ssize_t total_written=0;
2292 size_t numtowrite=0;
2297 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2299 START_PROFILE(SMBwritebraw);
2301 if (srv_is_signing_active()) {
2302 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2305 CHECK_FSP(fsp,conn);
2308 tcount = IVAL(inbuf,smb_vwv1);
2309 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2310 write_through = BITSETW(inbuf+smb_vwv7,0);
2312 /* We have to deal with slightly different formats depending
2313 on whether we are using the core+ or lanman1.0 protocol */
2315 if(Protocol <= PROTOCOL_COREPLUS) {
2316 numtowrite = SVAL(smb_buf(inbuf),-2);
2317 data = smb_buf(inbuf);
2319 numtowrite = SVAL(inbuf,smb_vwv10);
2320 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2323 /* force the error type */
2324 SCVAL(inbuf,smb_com,SMBwritec);
2325 SCVAL(outbuf,smb_com,SMBwritec);
2327 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2328 END_PROFILE(SMBwritebraw);
2329 return(ERROR_DOS(ERRDOS,ERRlock));
2333 nwritten = write_file(fsp,data,startpos,numtowrite);
2335 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2336 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2338 if (nwritten < (ssize_t)numtowrite) {
2339 END_PROFILE(SMBwritebraw);
2340 return(UNIXERROR(ERRHRD,ERRdiskfull));
2343 total_written = nwritten;
2345 /* Return a message to the redirector to tell it to send more bytes */
2346 SCVAL(outbuf,smb_com,SMBwritebraw);
2347 SSVALS(outbuf,smb_vwv0,-1);
2348 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2349 if (!send_smb(smbd_server_fd(),outbuf))
2350 exit_server("reply_writebraw: send_smb failed.");
2352 /* Now read the raw data into the buffer and write it */
2353 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2354 exit_server("secondary writebraw failed");
2357 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2358 numtowrite = smb_len(inbuf);
2360 /* Set up outbuf to return the correct return */
2361 outsize = set_message(outbuf,1,0,True);
2362 SCVAL(outbuf,smb_com,SMBwritec);
2363 SSVAL(outbuf,smb_vwv0,total_written);
2365 if (numtowrite != 0) {
2367 if (numtowrite > BUFFER_SIZE) {
2368 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2369 (unsigned int)numtowrite ));
2370 exit_server("secondary writebraw failed");
2373 if (tcount > nwritten+numtowrite) {
2374 DEBUG(3,("Client overestimated the write %d %d %d\n",
2375 (int)tcount,(int)nwritten,(int)numtowrite));
2378 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2379 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2381 exit_server("secondary writebraw failed");
2384 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2386 if (nwritten < (ssize_t)numtowrite) {
2387 SCVAL(outbuf,smb_rcls,ERRHRD);
2388 SSVAL(outbuf,smb_err,ERRdiskfull);
2392 total_written += nwritten;
2395 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2396 sync_file(conn,fsp);
2398 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2399 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2401 /* we won't return a status if write through is not selected - this follows what WfWg does */
2402 END_PROFILE(SMBwritebraw);
2403 if (!write_through && total_written==tcount) {
2405 #if RABBIT_PELLET_FIX
2407 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2408 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2410 if (!send_keepalive(smbd_server_fd()))
2411 exit_server("reply_writebraw: send of keepalive failed");
2419 /****************************************************************************
2420 Reply to a writeunlock (core+).
2421 ****************************************************************************/
2423 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2424 int size, int dum_buffsize)
2426 ssize_t nwritten = -1;
2430 NTSTATUS status = NT_STATUS_OK;
2431 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2433 START_PROFILE(SMBwriteunlock);
2435 CHECK_FSP(fsp,conn);
2438 numtowrite = SVAL(inbuf,smb_vwv1);
2439 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2440 data = smb_buf(inbuf) + 3;
2442 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2443 WRITE_LOCK,False)) {
2444 END_PROFILE(SMBwriteunlock);
2445 return ERROR_DOS(ERRDOS,ERRlock);
2448 /* The special X/Open SMB protocol handling of
2449 zero length writes is *NOT* done for
2454 nwritten = write_file(fsp,data,startpos,numtowrite);
2456 if (lp_syncalways(SNUM(conn)))
2457 sync_file(conn,fsp);
2459 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2460 END_PROFILE(SMBwriteunlock);
2461 return(UNIXERROR(ERRHRD,ERRdiskfull));
2465 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2466 (SMB_BIG_UINT)startpos);
2467 if (NT_STATUS_V(status)) {
2468 END_PROFILE(SMBwriteunlock);
2469 return ERROR_NT(status);
2473 outsize = set_message(outbuf,1,0,True);
2475 SSVAL(outbuf,smb_vwv0,nwritten);
2477 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2478 fsp->fnum, (int)numtowrite, (int)nwritten));
2480 END_PROFILE(SMBwriteunlock);
2484 /****************************************************************************
2486 ****************************************************************************/
2488 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2491 ssize_t nwritten = -1;
2494 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2496 START_PROFILE(SMBwrite);
2498 /* If it's an IPC, pass off the pipe handler. */
2500 END_PROFILE(SMBwrite);
2501 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2504 CHECK_FSP(fsp,conn);
2507 numtowrite = SVAL(inbuf,smb_vwv1);
2508 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2509 data = smb_buf(inbuf) + 3;
2511 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2512 END_PROFILE(SMBwrite);
2513 return ERROR_DOS(ERRDOS,ERRlock);
2517 * X/Open SMB protocol says that if smb_vwv1 is
2518 * zero then the file size should be extended or
2519 * truncated to the size given in smb_vwv[2-3].
2522 if(numtowrite == 0) {
2524 * This is actually an allocate call, and set EOF. JRA.
2526 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2528 END_PROFILE(SMBwrite);
2529 return ERROR_NT(NT_STATUS_DISK_FULL);
2531 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2533 END_PROFILE(SMBwrite);
2534 return ERROR_NT(NT_STATUS_DISK_FULL);
2537 nwritten = write_file(fsp,data,startpos,numtowrite);
2539 if (lp_syncalways(SNUM(conn)))
2540 sync_file(conn,fsp);
2542 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2543 END_PROFILE(SMBwrite);
2544 return(UNIXERROR(ERRHRD,ERRdiskfull));
2547 outsize = set_message(outbuf,1,0,True);
2549 SSVAL(outbuf,smb_vwv0,nwritten);
2551 if (nwritten < (ssize_t)numtowrite) {
2552 SCVAL(outbuf,smb_rcls,ERRHRD);
2553 SSVAL(outbuf,smb_err,ERRdiskfull);
2556 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2558 END_PROFILE(SMBwrite);
2562 /****************************************************************************
2563 Reply to a write and X.
2564 ****************************************************************************/
2566 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2568 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2569 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2570 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2571 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2572 ssize_t nwritten = -1;
2573 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2574 unsigned int smblen = smb_len(inbuf);
2576 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2577 START_PROFILE(SMBwriteX);
2579 /* If it's an IPC, pass off the pipe handler. */
2581 END_PROFILE(SMBwriteX);
2582 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2585 CHECK_FSP(fsp,conn);
2588 /* Deal with possible LARGE_WRITEX */
2590 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2592 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2593 END_PROFILE(SMBwriteX);
2594 return ERROR_DOS(ERRDOS,ERRbadmem);
2597 data = smb_base(inbuf) + smb_doff;
2599 if(CVAL(inbuf,smb_wct) == 14) {
2600 #ifdef LARGE_SMB_OFF_T
2602 * This is a large offset (64 bit) write.
2604 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2606 #else /* !LARGE_SMB_OFF_T */
2609 * Ensure we haven't been sent a >32 bit offset.
2612 if(IVAL(inbuf,smb_vwv12) != 0) {
2613 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2614 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2615 END_PROFILE(SMBwriteX);
2616 return ERROR_DOS(ERRDOS,ERRbadaccess);
2619 #endif /* LARGE_SMB_OFF_T */
2622 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2623 END_PROFILE(SMBwriteX);
2624 return ERROR_DOS(ERRDOS,ERRlock);
2627 /* X/Open SMB protocol says that, unlike SMBwrite
2628 if the length is zero then NO truncation is
2629 done, just a write of zero. To truncate a file,
2635 nwritten = write_file(fsp,data,startpos,numtowrite);
2637 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2638 END_PROFILE(SMBwriteX);
2639 return(UNIXERROR(ERRHRD,ERRdiskfull));
2642 set_message(outbuf,6,0,True);
2644 SSVAL(outbuf,smb_vwv2,nwritten);
2646 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2648 if (nwritten < (ssize_t)numtowrite) {
2649 SCVAL(outbuf,smb_rcls,ERRHRD);
2650 SSVAL(outbuf,smb_err,ERRdiskfull);
2653 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2654 fsp->fnum, (int)numtowrite, (int)nwritten));
2656 if (lp_syncalways(SNUM(conn)) || write_through)
2657 sync_file(conn,fsp);
2659 END_PROFILE(SMBwriteX);
2660 return chain_reply(inbuf,outbuf,length,bufsize);
2663 /****************************************************************************
2665 ****************************************************************************/
2667 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2673 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2674 START_PROFILE(SMBlseek);
2676 CHECK_FSP(fsp,conn);
2678 flush_write_cache(fsp, SEEK_FLUSH);
2680 mode = SVAL(inbuf,smb_vwv1) & 3;
2681 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2682 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2691 res = fsp->pos + startpos;
2702 if (umode == SEEK_END) {
2703 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2704 if(errno == EINVAL) {
2705 SMB_OFF_T current_pos = startpos;
2706 SMB_STRUCT_STAT sbuf;
2708 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2709 END_PROFILE(SMBlseek);
2710 return(UNIXERROR(ERRDOS,ERRnoaccess));
2713 current_pos += sbuf.st_size;
2715 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2720 END_PROFILE(SMBlseek);
2721 return(UNIXERROR(ERRDOS,ERRnoaccess));
2727 outsize = set_message(outbuf,2,0,True);
2728 SIVAL(outbuf,smb_vwv0,res);
2730 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2731 fsp->fnum, (double)startpos, (double)res, mode));
2733 END_PROFILE(SMBlseek);
2737 /****************************************************************************
2739 ****************************************************************************/
2741 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2743 int outsize = set_message(outbuf,0,0,True);
2744 uint16 fnum = SVAL(inbuf,smb_vwv0);
2745 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2746 START_PROFILE(SMBflush);
2749 CHECK_FSP(fsp,conn);
2752 file_sync_all(conn);
2754 sync_file(conn,fsp);
2757 DEBUG(3,("flush\n"));
2758 END_PROFILE(SMBflush);
2762 /****************************************************************************
2764 ****************************************************************************/
2766 int reply_exit(connection_struct *conn,
2767 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2770 START_PROFILE(SMBexit);
2772 file_close_pid(SVAL(inbuf,smb_pid));
2774 outsize = set_message(outbuf,0,0,True);
2776 DEBUG(3,("exit\n"));
2778 END_PROFILE(SMBexit);
2782 /****************************************************************************
2783 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2784 ****************************************************************************/
2786 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2789 extern struct current_user current_user;
2792 int32 eclass = 0, err = 0;
2793 files_struct *fsp = NULL;
2794 START_PROFILE(SMBclose);
2796 outsize = set_message(outbuf,0,0,True);
2798 /* If it's an IPC, pass off to the pipe handler. */
2800 END_PROFILE(SMBclose);
2801 return reply_pipe_close(conn, inbuf,outbuf);
2804 fsp = file_fsp(inbuf,smb_vwv0);
2807 * We can only use CHECK_FSP if we know it's not a directory.
2810 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2811 END_PROFILE(SMBclose);
2812 return ERROR_DOS(ERRDOS,ERRbadfid);
2815 if(fsp->is_directory) {
2817 * Special case - close NT SMB directory handle.
2819 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2820 close_file(fsp,True);
2823 * Close ordinary file.
2828 /* Save the name for time set in close. */
2829 pstrcpy( file_name, fsp->fsp_name);
2831 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2833 conn->num_files_open));
2836 * close_file() returns the unix errno if an error
2837 * was detected on close - normally this is due to
2838 * a disk full error. If not then it was probably an I/O error.
2841 if((close_err = close_file(fsp,True)) != 0) {
2843 END_PROFILE(SMBclose);
2844 return (UNIXERROR(ERRHRD,ERRgeneral));
2848 * Now take care of any time sent in the close.
2851 mtime = make_unix_date3(inbuf+smb_vwv1);
2853 /* try and set the date */
2854 set_filetime(conn, file_name, mtime);
2858 /* We have a cached error */
2860 END_PROFILE(SMBclose);
2861 return ERROR_DOS(eclass,err);
2864 END_PROFILE(SMBclose);
2868 /****************************************************************************
2869 Reply to a writeclose (Core+ protocol).
2870 ****************************************************************************/
2872 int reply_writeclose(connection_struct *conn,
2873 char *inbuf,char *outbuf, int size, int dum_buffsize)
2876 ssize_t nwritten = -1;
2882 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2883 START_PROFILE(SMBwriteclose);
2885 CHECK_FSP(fsp,conn);
2888 numtowrite = SVAL(inbuf,smb_vwv1);
2889 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2890 mtime = make_unix_date3(inbuf+smb_vwv4);
2891 data = smb_buf(inbuf) + 1;
2893 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2894 END_PROFILE(SMBwriteclose);
2895 return ERROR_DOS(ERRDOS,ERRlock);
2898 nwritten = write_file(fsp,data,startpos,numtowrite);
2900 set_filetime(conn, fsp->fsp_name,mtime);
2903 * More insanity. W2K only closes the file if writelen > 0.
2908 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2910 close_err = close_file(fsp,True);
2913 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2914 fsp->fnum, (int)numtowrite, (int)nwritten,
2915 conn->num_files_open));
2917 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2918 END_PROFILE(SMBwriteclose);
2919 return(UNIXERROR(ERRHRD,ERRdiskfull));
2922 if(close_err != 0) {
2924 END_PROFILE(SMBwriteclose);
2925 return(UNIXERROR(ERRHRD,ERRgeneral));
2928 outsize = set_message(outbuf,1,0,True);
2930 SSVAL(outbuf,smb_vwv0,nwritten);
2931 END_PROFILE(SMBwriteclose);
2935 /****************************************************************************
2937 ****************************************************************************/
2939 int reply_lock(connection_struct *conn,
2940 char *inbuf,char *outbuf, int length, int dum_buffsize)
2942 int outsize = set_message(outbuf,0,0,True);
2943 SMB_BIG_UINT count,offset;
2945 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2946 BOOL my_lock_ctx = False;
2948 START_PROFILE(SMBlock);
2950 CHECK_FSP(fsp,conn);
2952 release_level_2_oplocks_on_change(fsp);
2954 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2955 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2957 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2958 fsp->fd, fsp->fnum, (double)offset, (double)count));
2960 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2961 if (NT_STATUS_V(status)) {
2963 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2964 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2966 * A blocking lock was requested. Package up
2967 * this smb into a queued request and push it
2968 * onto the blocking lock queue.
2970 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2971 END_PROFILE(SMBlock);
2976 END_PROFILE(SMBlock);
2977 return ERROR_NT(status);
2980 END_PROFILE(SMBlock);
2984 /****************************************************************************
2986 ****************************************************************************/
2988 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2991 int outsize = set_message(outbuf,0,0,True);
2992 SMB_BIG_UINT count,offset;
2994 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2995 START_PROFILE(SMBunlock);
2997 CHECK_FSP(fsp,conn);
2999 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3000 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3002 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3003 if (NT_STATUS_V(status)) {
3004 END_PROFILE(SMBunlock);
3005 return ERROR_NT(status);
3008 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3009 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3011 END_PROFILE(SMBunlock);
3015 /****************************************************************************
3017 ****************************************************************************/
3019 int reply_tdis(connection_struct *conn,
3020 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3022 int outsize = set_message(outbuf,0,0,True);
3024 START_PROFILE(SMBtdis);
3026 vuid = SVAL(inbuf,smb_uid);
3029 DEBUG(4,("Invalid connection in tdis\n"));
3030 END_PROFILE(SMBtdis);
3031 return ERROR_DOS(ERRSRV,ERRinvnid);
3036 close_cnum(conn,vuid);
3038 END_PROFILE(SMBtdis);
3042 /****************************************************************************
3044 ****************************************************************************/
3046 int reply_echo(connection_struct *conn,
3047 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3049 int smb_reverb = SVAL(inbuf,smb_vwv0);
3051 unsigned int data_len = smb_buflen(inbuf);
3052 int outsize = set_message(outbuf,1,data_len,True);
3053 START_PROFILE(SMBecho);
3055 if (data_len > BUFFER_SIZE) {
3056 DEBUG(0,("reply_echo: data_len too large.\n"));
3057 END_PROFILE(SMBecho);
3061 /* copy any incoming data back out */
3063 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3065 if (smb_reverb > 100) {
3066 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3070 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3071 SSVAL(outbuf,smb_vwv0,seq_num);
3073 smb_setlen(outbuf,outsize - 4);
3075 if (!send_smb(smbd_server_fd(),outbuf))
3076 exit_server("reply_echo: send_smb failed.");
3079 DEBUG(3,("echo %d times\n", smb_reverb));
3083 END_PROFILE(SMBecho);
3087 /****************************************************************************
3088 Reply to a printopen.
3089 ****************************************************************************/
3091 int reply_printopen(connection_struct *conn,
3092 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3096 START_PROFILE(SMBsplopen);
3098 if (!CAN_PRINT(conn)) {
3099 END_PROFILE(SMBsplopen);
3100 return ERROR_DOS(ERRDOS,ERRnoaccess);
3103 /* Open for exclusive use, write only. */
3104 fsp = print_fsp_open(conn, NULL);
3107 END_PROFILE(SMBsplopen);
3108 return(UNIXERROR(ERRDOS,ERRnoaccess));
3111 outsize = set_message(outbuf,1,0,True);
3112 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3114 DEBUG(3,("openprint fd=%d fnum=%d\n",
3115 fsp->fd, fsp->fnum));
3117 END_PROFILE(SMBsplopen);
3121 /****************************************************************************
3122 Reply to a printclose.
3123 ****************************************************************************/
3125 int reply_printclose(connection_struct *conn,
3126 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3128 int outsize = set_message(outbuf,0,0,True);
3129 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3131 START_PROFILE(SMBsplclose);
3133 CHECK_FSP(fsp,conn);
3135 if (!CAN_PRINT(conn)) {
3136 END_PROFILE(SMBsplclose);
3137 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3140 DEBUG(3,("printclose fd=%d fnum=%d\n",
3141 fsp->fd,fsp->fnum));
3143 close_err = close_file(fsp,True);
3145 if(close_err != 0) {
3147 END_PROFILE(SMBsplclose);
3148 return(UNIXERROR(ERRHRD,ERRgeneral));
3151 END_PROFILE(SMBsplclose);
3155 /****************************************************************************
3156 Reply to a printqueue.
3157 ****************************************************************************/
3159 int reply_printqueue(connection_struct *conn,
3160 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3162 int outsize = set_message(outbuf,2,3,True);
3163 int max_count = SVAL(inbuf,smb_vwv0);
3164 int start_index = SVAL(inbuf,smb_vwv1);
3165 START_PROFILE(SMBsplretq);
3167 /* we used to allow the client to get the cnum wrong, but that
3168 is really quite gross and only worked when there was only
3169 one printer - I think we should now only accept it if they
3170 get it right (tridge) */
3171 if (!CAN_PRINT(conn)) {
3172 END_PROFILE(SMBsplretq);
3173 return ERROR_DOS(ERRDOS,ERRnoaccess);
3176 SSVAL(outbuf,smb_vwv0,0);
3177 SSVAL(outbuf,smb_vwv1,0);
3178 SCVAL(smb_buf(outbuf),0,1);
3179 SSVAL(smb_buf(outbuf),1,0);
3181 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3182 start_index, max_count));
3185 print_queue_struct *queue = NULL;
3186 print_status_struct status;
3187 char *p = smb_buf(outbuf) + 3;
3188 int count = print_queue_status(SNUM(conn), &queue, &status);
3189 int num_to_get = ABS(max_count);
3190 int first = (max_count>0?start_index:start_index+max_count+1);
3196 num_to_get = MIN(num_to_get,count-first);
3199 for (i=first;i<first+num_to_get;i++) {
3200 put_dos_date2(p,0,queue[i].time);
3201 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3202 SSVAL(p,5, queue[i].job);
3203 SIVAL(p,7,queue[i].size);
3205 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3210 outsize = set_message(outbuf,2,28*count+3,False);
3211 SSVAL(outbuf,smb_vwv0,count);
3212 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3213 SCVAL(smb_buf(outbuf),0,1);
3214 SSVAL(smb_buf(outbuf),1,28*count);
3219 DEBUG(3,("%d entries returned in queue\n",count));
3222 END_PROFILE(SMBsplretq);
3226 /****************************************************************************
3227 Reply to a printwrite.
3228 ****************************************************************************/
3230 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3233 int outsize = set_message(outbuf,0,0,True);
3235 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3237 START_PROFILE(SMBsplwr);
3239 if (!CAN_PRINT(conn)) {
3240 END_PROFILE(SMBsplwr);
3241 return ERROR_DOS(ERRDOS,ERRnoaccess);
3244 CHECK_FSP(fsp,conn);
3247 numtowrite = SVAL(smb_buf(inbuf),1);
3248 data = smb_buf(inbuf) + 3;
3250 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3251 END_PROFILE(SMBsplwr);
3252 return(UNIXERROR(ERRHRD,ERRdiskfull));
3255 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3257 END_PROFILE(SMBsplwr);
3261 /****************************************************************************
3262 The guts of the mkdir command, split out so it may be called by the NT SMB
3264 ****************************************************************************/
3266 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3268 BOOL bad_path = False;
3269 SMB_STRUCT_STAT sbuf;
3272 unix_convert(directory,conn,0,&bad_path,&sbuf);
3274 if( strchr_m(directory, ':')) {
3275 return NT_STATUS_NOT_A_DIRECTORY;
3278 if (ms_has_wild(directory)) {
3279 return NT_STATUS_OBJECT_NAME_INVALID;
3283 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3286 if (check_name(directory, conn))
3287 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3290 if(errno == ENOENT) {
3291 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3293 return map_nt_error_from_unix(errno);
3296 return NT_STATUS_OK;
3299 /****************************************************************************
3301 ****************************************************************************/
3303 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3308 START_PROFILE(SMBmkdir);
3310 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3311 if (!NT_STATUS_IS_OK(status)) {
3312 END_PROFILE(SMBmkdir);
3313 return ERROR_NT(status);
3316 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3318 status = mkdir_internal(conn, directory);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 END_PROFILE(SMBmkdir);
3321 return ERROR_NT(status);
3324 outsize = set_message(outbuf,0,0,True);
3326 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3328 END_PROFILE(SMBmkdir);
3332 /****************************************************************************
3333 Static function used by reply_rmdir to delete an entire directory
3334 tree recursively. Return False on ok, True on fail.
3335 ****************************************************************************/
3337 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3339 const char *dname = NULL;
3341 void *dirptr = OpenDir(conn, directory, False);
3346 while((dname = ReadDirName(dirptr))) {
3350 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3353 /* Construct the full name. */
3354 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3360 pstrcpy(fullname, directory);
3361 pstrcat(fullname, "/");
3362 pstrcat(fullname, dname);
3364 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3369 if(st.st_mode & S_IFDIR) {
3370 if(recursive_rmdir(conn, fullname)!=0) {
3374 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3378 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3387 /****************************************************************************
3388 The internals of the rmdir code - called elsewhere.
3389 ****************************************************************************/
3391 BOOL rmdir_internals(connection_struct *conn, char *directory)
3395 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3396 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3398 * Check to see if the only thing in this directory are
3399 * vetoed files/directories. If so then delete them and
3400 * retry. If we fail to delete any of them (and we *don't*
3401 * do a recursive delete) then fail the rmdir.
3403 BOOL all_veto_files = True;
3405 void *dirptr = OpenDir(conn, directory, False);
3407 if(dirptr != NULL) {
3408 int dirpos = TellDir(dirptr);
3409 while ((dname = ReadDirName(dirptr))) {
3410 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3412 if(!IS_VETO_PATH(conn, dname)) {
3413 all_veto_files = False;
3418 if(all_veto_files) {
3419 SeekDir(dirptr,dirpos);
3420 while ((dname = ReadDirName(dirptr))) {
3424 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3427 /* Construct the full name. */
3428 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3433 pstrcpy(fullname, directory);
3434 pstrcat(fullname, "/");
3435 pstrcat(fullname, dname);
3437 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3439 if(st.st_mode & S_IFDIR) {
3440 if(lp_recursive_veto_delete(SNUM(conn))) {
3441 if(recursive_rmdir(conn, fullname) != 0)
3444 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3446 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3450 /* Retry the rmdir */
3451 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3461 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3466 /****************************************************************************
3468 ****************************************************************************/
3470 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3475 BOOL bad_path = False;
3476 SMB_STRUCT_STAT sbuf;
3478 START_PROFILE(SMBrmdir);
3480 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3481 if (!NT_STATUS_IS_OK(status)) {
3482 END_PROFILE(SMBrmdir);
3483 return ERROR_NT(status);
3486 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3488 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3490 END_PROFILE(SMBrmdir);
3491 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3494 if (check_name(directory,conn)) {
3495 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3496 ok = rmdir_internals(conn, directory);
3500 END_PROFILE(SMBrmdir);
3501 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3504 outsize = set_message(outbuf,0,0,True);
3506 DEBUG( 3, ( "rmdir %s\n", directory ) );
3508 END_PROFILE(SMBrmdir);
3512 /*******************************************************************
3513 Resolve wildcards in a filename rename.
3514 Note that name is in UNIX charset and thus potentially can be more
3515 than fstring buffer (255 bytes) especially in default UTF-8 case.
3516 Therefore, we use pstring inside and all calls should ensure that
3517 name2 is at least pstring-long (they do already)
3518 ********************************************************************/
3520 static BOOL resolve_wildcards(const char *name1, char *name2)
3522 pstring root1,root2;
3524 char *p,*p2, *pname1, *pname2;
3525 int available_space, actual_space;
3528 pname1 = strrchr_m(name1,'/');
3529 pname2 = strrchr_m(name2,'/');
3531 if (!pname1 || !pname2)
3534 pstrcpy(root1,pname1);
3535 pstrcpy(root2,pname2);
3536 p = strrchr_m(root1,'.');
3543 p = strrchr_m(root2,'.');
3557 } else if (*p2 == '*') {
3573 } else if (*p2 == '*') {
3583 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3586 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3587 if (actual_space >= available_space - 1) {
3588 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3589 actual_space - available_space));
3592 pstrcpy_base(pname2, root2, name2);
3598 /****************************************************************************
3599 Ensure open files have their names updates.
3600 ****************************************************************************/
3602 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3605 BOOL did_rename = False;
3607 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3608 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3609 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3610 fsp->fsp_name, newname ));
3611 string_set(&fsp->fsp_name, newname);
3616 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3617 (unsigned int)dev, (double)inode, newname ));
3620 /****************************************************************************
3621 Rename an open file - given an fsp.
3622 ****************************************************************************/
3624 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3626 SMB_STRUCT_STAT sbuf;
3627 BOOL bad_path = False;
3628 pstring newname_last_component;
3629 NTSTATUS error = NT_STATUS_OK;
3634 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3636 /* Quick check for "." and ".." */
3637 if (!bad_path && newname_last_component[0] == '.') {
3638 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3639 return NT_STATUS_ACCESS_DENIED;
3642 if (!rcdest && bad_path) {
3643 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3646 /* Ensure newname contains a '/' */
3647 if(strrchr_m(newname,'/') == 0) {
3650 pstrcpy(tmpstr, "./");
3651 pstrcat(tmpstr, newname);
3652 pstrcpy(newname, tmpstr);
3656 * Check for special case with case preserving and not
3657 * case sensitive. If the old last component differs from the original
3658 * last component only by case, then we should allow
3659 * the rename (user is trying to change the case of the
3663 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3664 strequal(newname, fsp->fsp_name)) {
3666 pstring newname_modified_last_component;
3669 * Get the last component of the modified name.
3670 * Note that we guarantee that newname contains a '/'
3673 p = strrchr_m(newname,'/');
3674 pstrcpy(newname_modified_last_component,p+1);
3676 if(strcsequal(newname_modified_last_component,
3677 newname_last_component) == False) {
3679 * Replace the modified last component with
3682 pstrcpy(p+1, newname_last_component);
3687 * If the src and dest names are identical - including case,
3688 * don't do the rename, just return success.
3691 if (strcsequal(fsp->fsp_name, newname)) {
3692 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3694 return NT_STATUS_OK;
3697 dest_exists = vfs_object_exist(conn,newname,NULL);
3699 if(!replace_if_exists && dest_exists) {
3700 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3701 fsp->fsp_name,newname));
3702 return NT_STATUS_OBJECT_NAME_COLLISION;
3705 error = can_rename(newname,conn,attrs,&sbuf);
3707 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3708 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3709 nt_errstr(error), fsp->fsp_name,newname));
3710 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3711 error = NT_STATUS_ACCESS_DENIED;
3715 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3716 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3717 fsp->fsp_name,newname));
3718 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3719 return NT_STATUS_OK;
3722 if (errno == ENOTDIR || errno == EISDIR)
3723 error = NT_STATUS_OBJECT_NAME_COLLISION;
3725 error = map_nt_error_from_unix(errno);
3727 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3728 nt_errstr(error), fsp->fsp_name,newname));
3733 /****************************************************************************
3734 The guts of the rename command, split out so it may be called by the NT SMB
3736 ****************************************************************************/
3738 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3742 pstring last_component_src;
3743 pstring last_component_dest;
3746 BOOL bad_path_src = False;
3747 BOOL bad_path_dest = False;
3749 NTSTATUS error = NT_STATUS_OK;
3752 SMB_STRUCT_STAT sbuf1, sbuf2;
3754 *directory = *mask = 0;
3759 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3760 if (!rc && bad_path_src) {
3761 if (ms_has_wild(last_component_src))
3762 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3763 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3766 /* Quick check for "." and ".." */
3767 if (last_component_src[0] == '.') {
3768 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3769 return NT_STATUS_OBJECT_NAME_INVALID;
3773 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3775 /* Quick check for "." and ".." */
3776 if (last_component_dest[0] == '.') {
3777 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3778 return NT_STATUS_OBJECT_NAME_INVALID;
3783 * Split the old name into directory and last component
3784 * strings. Note that unix_convert may have stripped off a
3785 * leading ./ from both name and newname if the rename is
3786 * at the root of the share. We need to make sure either both
3787 * name and newname contain a / character or neither of them do
3788 * as this is checked in resolve_wildcards().
3791 p = strrchr_m(name,'/');
3793 pstrcpy(directory,".");
3797 pstrcpy(directory,name);
3799 *p = '/'; /* Replace needed for exceptional test below. */
3803 * We should only check the mangled cache
3804 * here if unix_convert failed. This means
3805 * that the path in 'mask' doesn't exist
3806 * on the file system and so we need to look
3807 * for a possible mangle. This patch from
3808 * Tine Smukavec <valentin.smukavec@hermes.si>.
3811 if (!rc && mangle_is_mangled(mask))
3812 mangle_check_cache( mask, sizeof(pstring)-1 );
3814 has_wild = ms_has_wild(mask);
3818 * No wildcards - just process the one file.
3820 BOOL is_short_name = mangle_is_8_3(name, True);
3822 /* Add a terminating '/' to the directory name. */
3823 pstrcat(directory,"/");
3824 pstrcat(directory,mask);
3826 /* Ensure newname contains a '/' also */
3827 if(strrchr_m(newname,'/') == 0) {
3830 pstrcpy(tmpstr, "./");
3831 pstrcat(tmpstr, newname);
3832 pstrcpy(newname, tmpstr);
3835 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3836 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3837 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3838 newname, last_component_dest, is_short_name));
3841 * Check for special case with case preserving and not
3842 * case sensitive, if directory and newname are identical,
3843 * and the old last component differs from the original
3844 * last component only by case, then we should allow
3845 * the rename (user is trying to change the case of the
3848 if((conn->case_sensitive == False) &&
3849 (((conn->case_preserve == True) &&
3850 (is_short_name == False)) ||
3851 ((conn->short_case_preserve == True) &&
3852 (is_short_name == True))) &&
3853 strcsequal(directory, newname)) {
3854 pstring modified_last_component;
3857 * Get the last component of the modified name.
3858 * Note that we guarantee that newname contains a '/'
3861 p = strrchr_m(newname,'/');
3862 pstrcpy(modified_last_component,p+1);
3864 if(strcsequal(modified_last_component,
3865 last_component_dest) == False) {
3867 * Replace the modified last component with
3870 pstrcpy(p+1, last_component_dest);
3874 resolve_wildcards(directory,newname);
3877 * The source object must exist.
3880 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3881 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3882 directory,newname));
3884 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3886 * Must return different errors depending on whether the parent
3887 * directory existed or not.
3890 p = strrchr_m(directory, '/');
3892 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3894 if (vfs_object_exist(conn, directory, NULL))
3895 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3896 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3898 error = map_nt_error_from_unix(errno);
3899 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3900 nt_errstr(error), directory,newname));
3905 if (!rcdest && bad_path_dest) {
3906 if (ms_has_wild(last_component_dest))
3907 return NT_STATUS_OBJECT_NAME_INVALID;
3908 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3911 error = can_rename(directory,conn,attrs,&sbuf1);
3913 if (!NT_STATUS_IS_OK(error)) {
3914 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3915 nt_errstr(error), directory,newname));
3920 * If the src and dest names are identical - including case,
3921 * don't do the rename, just return success.
3924 if (strcsequal(directory, newname)) {
3925 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3926 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3927 return NT_STATUS_OK;
3930 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3931 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3932 directory,newname));
3933 return NT_STATUS_OBJECT_NAME_COLLISION;
3936 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3937 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3938 directory,newname));
3939 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3940 return NT_STATUS_OK;
3943 if (errno == ENOTDIR || errno == EISDIR)
3944 error = NT_STATUS_OBJECT_NAME_COLLISION;
3946 error = map_nt_error_from_unix(errno);
3948 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3949 nt_errstr(error), directory,newname));
3954 * Wildcards - process each file that matches.
3956 void *dirptr = NULL;
3960 if (check_name(directory,conn))
3961 dirptr = OpenDir(conn, directory, True);
3964 error = NT_STATUS_NO_SUCH_FILE;
3965 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3967 if (strequal(mask,"????????.???"))
3970 while ((dname = ReadDirName(dirptr))) {
3972 BOOL sysdir_entry = False;
3974 pstrcpy(fname,dname);
3976 /* Quick check for "." and ".." */
3977 if (fname[0] == '.') {
3978 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3980 sysdir_entry = True;
3987 if(!mask_match(fname, mask, conn->case_sensitive))
3991 error = NT_STATUS_OBJECT_NAME_INVALID;
3995 error = NT_STATUS_ACCESS_DENIED;
3996 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3997 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3998 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3999 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4002 error = can_rename(fname,conn,attrs,&sbuf1);
4003 if (!NT_STATUS_IS_OK(error)) {
4004 DEBUG(6,("rename %s refused\n", fname));
4007 pstrcpy(destname,newname);
4009 if (!resolve_wildcards(fname,destname)) {
4010 DEBUG(6,("resolve_wildcards %s %s failed\n",
4015 if (strcsequal(fname,destname)) {
4016 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4017 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4019 error = NT_STATUS_OK;
4023 if (!replace_if_exists &&
4024 vfs_file_exist(conn,destname, NULL)) {
4025 DEBUG(6,("file_exist %s\n", destname));
4026 error = NT_STATUS_OBJECT_NAME_COLLISION;
4030 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4031 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4033 error = NT_STATUS_OK;
4035 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4040 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4041 if (!rcdest && bad_path_dest) {
4042 if (ms_has_wild(last_component_dest))
4043 return NT_STATUS_OBJECT_NAME_INVALID;
4044 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4049 if (count == 0 && NT_STATUS_IS_OK(error)) {
4050 error = map_nt_error_from_unix(errno);
4056 /****************************************************************************
4058 ****************************************************************************/
4060 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4067 uint16 attrs = SVAL(inbuf,smb_vwv0);
4070 START_PROFILE(SMBmv);
4072 p = smb_buf(inbuf) + 1;
4073 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4074 if (!NT_STATUS_IS_OK(status)) {
4076 return ERROR_NT(status);
4079 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4080 if (!NT_STATUS_IS_OK(status)) {
4082 return ERROR_NT(status);
4085 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4086 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4088 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4090 status = rename_internals(conn, name, newname, attrs, False);
4091 if (!NT_STATUS_IS_OK(status)) {
4093 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4094 /* We have re-scheduled this call. */
4095 clear_cached_errors();
4098 return ERROR_NT(status);
4102 * Win2k needs a changenotify request response before it will
4103 * update after a rename..
4105 process_pending_change_notify_queue((time_t)0);
4106 outsize = set_message(outbuf,0,0,True);
4112 /*******************************************************************
4113 Copy a file as part of a reply_copy.
4114 ******************************************************************/
4116 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4117 int count,BOOL target_is_directory, int *err_ret)
4120 SMB_STRUCT_STAT src_sbuf, sbuf2;
4122 files_struct *fsp1,*fsp2;
4128 pstrcpy(dest,dest1);
4129 if (target_is_directory) {
4130 char *p = strrchr_m(src,'/');
4139 if (!vfs_file_exist(conn,src,&src_sbuf))
4142 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4143 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4149 if (!target_is_directory && count)
4150 ofun = FILE_EXISTS_OPEN;
4152 dosattrs = dos_mode(conn, src, &src_sbuf);
4153 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4154 ZERO_STRUCTP(&sbuf2);
4156 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4157 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4160 close_file(fsp1,False);
4164 if ((ofun&3) == 1) {
4165 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4166 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4168 * Stop the copy from occurring.
4171 src_sbuf.st_size = 0;
4175 if (src_sbuf.st_size)
4176 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4178 close_file(fsp1,False);
4180 /* Ensure the modtime is set correctly on the destination file. */
4181 fsp2->pending_modtime = src_sbuf.st_mtime;
4184 * As we are opening fsp1 read-only we only expect
4185 * an error on close on fsp2 if we are out of space.
4186 * Thus we don't look at the error return from the
4189 *err_ret = close_file(fsp2,False);
4191 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4194 /****************************************************************************
4195 Reply to a file copy.
4196 ****************************************************************************/
4198 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4203 pstring mask,newname;
4206 int error = ERRnoaccess;
4210 int tid2 = SVAL(inbuf,smb_vwv0);
4211 int ofun = SVAL(inbuf,smb_vwv1);
4212 int flags = SVAL(inbuf,smb_vwv2);
4213 BOOL target_is_directory=False;
4214 BOOL bad_path1 = False;
4215 BOOL bad_path2 = False;
4217 SMB_STRUCT_STAT sbuf1, sbuf2;
4220 START_PROFILE(SMBcopy);
4222 *directory = *mask = 0;
4225 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4226 if (!NT_STATUS_IS_OK(status)) {
4227 END_PROFILE(SMBcopy);
4228 return ERROR_NT(status);
4230 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4231 if (!NT_STATUS_IS_OK(status)) {
4232 END_PROFILE(SMBcopy);
4233 return ERROR_NT(status);
4236 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4238 if (tid2 != conn->cnum) {
4239 /* can't currently handle inter share copies XXXX */
4240 DEBUG(3,("Rejecting inter-share copy\n"));
4241 END_PROFILE(SMBcopy);
4242 return ERROR_DOS(ERRSRV,ERRinvdevice);
4245 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4246 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4248 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4249 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4251 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4253 if ((flags&1) && target_is_directory) {
4254 END_PROFILE(SMBcopy);
4255 return ERROR_DOS(ERRDOS,ERRbadfile);
4258 if ((flags&2) && !target_is_directory) {
4259 END_PROFILE(SMBcopy);
4260 return ERROR_DOS(ERRDOS,ERRbadpath);
4263 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4264 /* wants a tree copy! XXXX */
4265 DEBUG(3,("Rejecting tree copy\n"));
4266 END_PROFILE(SMBcopy);
4267 return ERROR_DOS(ERRSRV,ERRerror);
4270 p = strrchr_m(name,'/');
4272 pstrcpy(directory,"./");
4276 pstrcpy(directory,name);
4281 * We should only check the mangled cache
4282 * here if unix_convert failed. This means
4283 * that the path in 'mask' doesn't exist
4284 * on the file system and so we need to look
4285 * for a possible mangle. This patch from
4286 * Tine Smukavec <valentin.smukavec@hermes.si>.
4289 if (!rc && mangle_is_mangled(mask))
4290 mangle_check_cache( mask, sizeof(pstring)-1 );
4292 has_wild = ms_has_wild(mask);
4295 pstrcat(directory,"/");
4296 pstrcat(directory,mask);
4297 if (resolve_wildcards(directory,newname) &&
4298 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4302 END_PROFILE(SMBcopy);
4303 return(UNIXERROR(ERRHRD,ERRgeneral));
4306 exists = vfs_file_exist(conn,directory,NULL);
4309 void *dirptr = NULL;
4313 if (check_name(directory,conn))
4314 dirptr = OpenDir(conn, directory, True);
4319 if (strequal(mask,"????????.???"))
4322 while ((dname = ReadDirName(dirptr))) {
4324 pstrcpy(fname,dname);
4326 if(!mask_match(fname, mask, conn->case_sensitive))
4329 error = ERRnoaccess;
4330 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4331 pstrcpy(destname,newname);
4332 if (resolve_wildcards(fname,destname) &&
4333 copy_file(fname,destname,conn,ofun,
4334 count,target_is_directory,&err))
4336 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4344 /* Error on close... */
4346 END_PROFILE(SMBcopy);
4347 return(UNIXERROR(ERRHRD,ERRgeneral));
4351 END_PROFILE(SMBcopy);
4352 return ERROR_DOS(ERRDOS,error);
4354 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4355 unix_ERR_class = ERRDOS;
4356 unix_ERR_code = ERRbadpath;
4358 END_PROFILE(SMBcopy);
4359 return(UNIXERROR(ERRDOS,error));
4363 outsize = set_message(outbuf,1,0,True);
4364 SSVAL(outbuf,smb_vwv0,count);
4366 END_PROFILE(SMBcopy);
4370 /****************************************************************************
4372 ****************************************************************************/
4374 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4382 START_PROFILE(pathworks_setdir);
4385 if (!CAN_SETDIR(snum)) {
4386 END_PROFILE(pathworks_setdir);
4387 return ERROR_DOS(ERRDOS,ERRnoaccess);
4390 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4391 if (!NT_STATUS_IS_OK(status)) {
4392 END_PROFILE(pathworks_setdir);
4393 return ERROR_NT(status);
4396 if (strlen(newdir) == 0) {
4399 ok = vfs_directory_exist(conn,newdir,NULL);
4401 string_set(&conn->connectpath,newdir);
4405 END_PROFILE(pathworks_setdir);
4406 return ERROR_DOS(ERRDOS,ERRbadpath);
4409 outsize = set_message(outbuf,0,0,True);
4410 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4412 DEBUG(3,("setdir %s\n", newdir));
4414 END_PROFILE(pathworks_setdir);
4418 /****************************************************************************
4419 Get a lock pid, dealing with large count requests.
4420 ****************************************************************************/
4422 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4424 if(!large_file_format)
4425 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4427 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4430 /****************************************************************************
4431 Get a lock count, dealing with large count requests.
4432 ****************************************************************************/
4434 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4436 SMB_BIG_UINT count = 0;
4438 if(!large_file_format) {
4439 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4442 #if defined(HAVE_LONGLONG)
4443 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4444 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4445 #else /* HAVE_LONGLONG */
4448 * NT4.x seems to be broken in that it sends large file (64 bit)
4449 * lockingX calls even if the CAP_LARGE_FILES was *not*
4450 * negotiated. For boxes without large unsigned ints truncate the
4451 * lock count by dropping the top 32 bits.
4454 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4455 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4456 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4457 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4458 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4461 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4462 #endif /* HAVE_LONGLONG */
4468 #if !defined(HAVE_LONGLONG)
4469 /****************************************************************************
4470 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4471 ****************************************************************************/
4473 static uint32 map_lock_offset(uint32 high, uint32 low)
4477 uint32 highcopy = high;
4480 * Try and find out how many significant bits there are in high.
4483 for(i = 0; highcopy; i++)
4487 * We use 31 bits not 32 here as POSIX
4488 * lock offsets may not be negative.
4491 mask = (~0) << (31 - i);
4494 return 0; /* Fail. */
4500 #endif /* !defined(HAVE_LONGLONG) */
4502 /****************************************************************************
4503 Get a lock offset, dealing with large offset requests.
4504 ****************************************************************************/
4506 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4508 SMB_BIG_UINT offset = 0;
4512 if(!large_file_format) {
4513 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4516 #if defined(HAVE_LONGLONG)
4517 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4518 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4519 #else /* HAVE_LONGLONG */
4522 * NT4.x seems to be broken in that it sends large file (64 bit)
4523 * lockingX calls even if the CAP_LARGE_FILES was *not*
4524 * negotiated. For boxes without large unsigned ints mangle the
4525 * lock offset by mapping the top 32 bits onto the lower 32.
4528 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4529 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4530 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4533 if((new_low = map_lock_offset(high, low)) == 0) {
4535 return (SMB_BIG_UINT)-1;
4538 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4539 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4540 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4541 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4544 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4545 #endif /* HAVE_LONGLONG */
4551 /****************************************************************************
4552 Reply to a lockingX request.
4553 ****************************************************************************/
4555 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4557 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4558 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4559 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4560 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4561 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4562 SMB_BIG_UINT count = 0, offset = 0;
4564 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4567 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4569 BOOL my_lock_ctx = False;
4572 START_PROFILE(SMBlockingX);
4574 CHECK_FSP(fsp,conn);
4576 data = smb_buf(inbuf);
4578 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4579 /* we don't support these - and CANCEL_LOCK makes w2k
4580 and XP reboot so I don't really want to be
4581 compatible! (tridge) */
4582 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4585 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4586 /* Need to make this like a cancel.... JRA. */
4587 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4590 /* Check if this is an oplock break on a file
4591 we have granted an oplock on.
4593 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4594 /* Client can insist on breaking to none. */
4595 BOOL break_to_none = (oplocklevel == 0);
4597 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4598 (unsigned int)oplocklevel, fsp->fnum ));
4601 * Make sure we have granted an exclusive or batch oplock on this file.
4604 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4605 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4606 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4608 /* if this is a pure oplock break request then don't send a reply */
4609 if (num_locks == 0 && num_ulocks == 0) {
4610 END_PROFILE(SMBlockingX);
4613 END_PROFILE(SMBlockingX);
4614 return ERROR_DOS(ERRDOS,ERRlock);
4618 if (remove_oplock(fsp, break_to_none) == False) {
4619 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4623 /* if this is a pure oplock break request then don't send a reply */
4624 if (num_locks == 0 && num_ulocks == 0) {
4625 /* Sanity check - ensure a pure oplock break is not a
4627 if(CVAL(inbuf,smb_vwv0) != 0xff)
4628 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4629 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4630 END_PROFILE(SMBlockingX);
4636 * We do this check *after* we have checked this is not a oplock break
4637 * response message. JRA.
4640 release_level_2_oplocks_on_change(fsp);
4642 /* Data now points at the beginning of the list
4643 of smb_unlkrng structs */
4644 for(i = 0; i < (int)num_ulocks; i++) {
4645 lock_pid = get_lock_pid( data, i, large_file_format);
4646 count = get_lock_count( data, i, large_file_format);
4647 offset = get_lock_offset( data, i, large_file_format, &err);
4650 * There is no error code marked "stupid client bug".... :-).
4653 END_PROFILE(SMBlockingX);
4654 return ERROR_DOS(ERRDOS,ERRnoaccess);
4657 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4658 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4660 status = do_unlock(fsp,conn,lock_pid,count,offset);
4661 if (NT_STATUS_V(status)) {
4662 END_PROFILE(SMBlockingX);
4663 return ERROR_NT(status);
4667 /* Setup the timeout in seconds. */
4669 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4671 /* Now do any requested locks */
4672 data += ((large_file_format ? 20 : 10)*num_ulocks);
4674 /* Data now points at the beginning of the list
4675 of smb_lkrng structs */
4677 for(i = 0; i < (int)num_locks; i++) {
4678 lock_pid = get_lock_pid( data, i, large_file_format);
4679 count = get_lock_count( data, i, large_file_format);
4680 offset = get_lock_offset( data, i, large_file_format, &err);
4683 * There is no error code marked "stupid client bug".... :-).
4686 END_PROFILE(SMBlockingX);
4687 return ERROR_DOS(ERRDOS,ERRnoaccess);
4690 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4691 (double)offset, (double)count, (unsigned int)lock_pid,
4692 fsp->fsp_name, (int)lock_timeout ));
4694 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4695 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4696 if (NT_STATUS_V(status)) {
4698 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4699 * Even if it's our own lock context, we need to wait here as
4700 * there may be an unlock on the way.
4701 * So I removed a "&& !my_lock_ctx" from the following
4702 * if statement. JRA.
4704 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4706 * A blocking lock was requested. Package up
4707 * this smb into a queued request and push it
4708 * onto the blocking lock queue.
4710 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4711 END_PROFILE(SMBlockingX);
4719 /* If any of the above locks failed, then we must unlock
4720 all of the previous locks (X/Open spec). */
4721 if (i != num_locks && num_locks != 0) {
4723 * Ensure we don't do a remove on the lock that just failed,
4724 * as under POSIX rules, if we have a lock already there, we
4725 * will delete it (and we shouldn't) .....
4727 for(i--; i >= 0; i--) {
4728 lock_pid = get_lock_pid( data, i, large_file_format);
4729 count = get_lock_count( data, i, large_file_format);
4730 offset = get_lock_offset( data, i, large_file_format, &err);
4733 * There is no error code marked "stupid client bug".... :-).
4736 END_PROFILE(SMBlockingX);
4737 return ERROR_DOS(ERRDOS,ERRnoaccess);
4740 do_unlock(fsp,conn,lock_pid,count,offset);
4742 END_PROFILE(SMBlockingX);
4743 return ERROR_NT(status);
4746 set_message(outbuf,2,0,True);
4748 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4749 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4751 END_PROFILE(SMBlockingX);
4752 return chain_reply(inbuf,outbuf,length,bufsize);
4755 /****************************************************************************
4756 Reply to a SMBreadbmpx (read block multiplex) request.
4757 ****************************************************************************/
4759 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4770 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4771 START_PROFILE(SMBreadBmpx);
4773 /* this function doesn't seem to work - disable by default */
4774 if (!lp_readbmpx()) {
4775 END_PROFILE(SMBreadBmpx);
4776 return ERROR_DOS(ERRSRV,ERRuseSTD);
4779 outsize = set_message(outbuf,8,0,True);
4781 CHECK_FSP(fsp,conn);
4784 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4785 maxcount = SVAL(inbuf,smb_vwv3);
4787 data = smb_buf(outbuf);
4788 pad = ((long)data)%4;
4793 max_per_packet = bufsize-(outsize+pad);
4797 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4798 END_PROFILE(SMBreadBmpx);
4799 return ERROR_DOS(ERRDOS,ERRlock);
4803 size_t N = MIN(max_per_packet,tcount-total_read);
4805 nread = read_file(fsp,data,startpos,N);
4810 if (nread < (ssize_t)N)
4811 tcount = total_read + nread;
4813 set_message(outbuf,8,nread,False);
4814 SIVAL(outbuf,smb_vwv0,startpos);
4815 SSVAL(outbuf,smb_vwv2,tcount);
4816 SSVAL(outbuf,smb_vwv6,nread);
4817 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4819 if (!send_smb(smbd_server_fd(),outbuf))
4820 exit_server("reply_readbmpx: send_smb failed.");
4822 total_read += nread;
4824 } while (total_read < (ssize_t)tcount);
4826 END_PROFILE(SMBreadBmpx);
4830 /****************************************************************************
4831 Reply to a SMBsetattrE.
4832 ****************************************************************************/
4834 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4836 struct utimbuf unix_times;
4838 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4839 START_PROFILE(SMBsetattrE);
4841 outsize = set_message(outbuf,0,0,True);
4843 if(!fsp || (fsp->conn != conn)) {
4844 END_PROFILE(SMBgetattrE);
4845 return ERROR_DOS(ERRDOS,ERRbadfid);
4849 * Convert the DOS times into unix times. Ignore create
4850 * time as UNIX can't set this.
4853 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4854 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4857 * Patch from Ray Frush <frush@engr.colostate.edu>
4858 * Sometimes times are sent as zero - ignore them.
4861 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4862 /* Ignore request */
4863 if( DEBUGLVL( 3 ) ) {
4864 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4865 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4867 END_PROFILE(SMBsetattrE);
4869 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4870 /* set modify time = to access time if modify time was 0 */
4871 unix_times.modtime = unix_times.actime;
4874 /* Set the date on this file */
4875 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4876 END_PROFILE(SMBsetattrE);
4877 return ERROR_DOS(ERRDOS,ERRnoaccess);
4880 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4881 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4883 END_PROFILE(SMBsetattrE);
4888 /* Back from the dead for OS/2..... JRA. */
4890 /****************************************************************************
4891 Reply to a SMBwritebmpx (write block multiplex primary) request.
4892 ****************************************************************************/
4894 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4897 ssize_t nwritten = -1;
4904 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4905 START_PROFILE(SMBwriteBmpx);
4907 CHECK_FSP(fsp,conn);
4911 tcount = SVAL(inbuf,smb_vwv1);
4912 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4913 write_through = BITSETW(inbuf+smb_vwv7,0);
4914 numtowrite = SVAL(inbuf,smb_vwv10);
4915 smb_doff = SVAL(inbuf,smb_vwv11);
4917 data = smb_base(inbuf) + smb_doff;
4919 /* If this fails we need to send an SMBwriteC response,
4920 not an SMBwritebmpx - set this up now so we don't forget */
4921 SCVAL(outbuf,smb_com,SMBwritec);
4923 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4924 END_PROFILE(SMBwriteBmpx);
4925 return(ERROR_DOS(ERRDOS,ERRlock));
4928 nwritten = write_file(fsp,data,startpos,numtowrite);
4930 if(lp_syncalways(SNUM(conn)) || write_through)
4931 sync_file(conn,fsp);
4933 if(nwritten < (ssize_t)numtowrite) {
4934 END_PROFILE(SMBwriteBmpx);
4935 return(UNIXERROR(ERRHRD,ERRdiskfull));
4938 /* If the maximum to be written to this file
4939 is greater than what we just wrote then set
4940 up a secondary struct to be attached to this
4941 fd, we will use this to cache error messages etc. */
4943 if((ssize_t)tcount > nwritten) {
4944 write_bmpx_struct *wbms;
4945 if(fsp->wbmpx_ptr != NULL)
4946 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4948 wbms = SMB_MALLOC_P(write_bmpx_struct);
4950 DEBUG(0,("Out of memory in reply_readmpx\n"));
4951 END_PROFILE(SMBwriteBmpx);
4952 return(ERROR_DOS(ERRSRV,ERRnoresource));
4954 wbms->wr_mode = write_through;
4955 wbms->wr_discard = False; /* No errors yet */
4956 wbms->wr_total_written = nwritten;
4957 wbms->wr_errclass = 0;
4959 fsp->wbmpx_ptr = wbms;
4962 /* We are returning successfully, set the message type back to
4964 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4966 outsize = set_message(outbuf,1,0,True);
4968 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4970 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4971 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4973 if (write_through && tcount==nwritten) {
4974 /* We need to send both a primary and a secondary response */
4975 smb_setlen(outbuf,outsize - 4);
4976 if (!send_smb(smbd_server_fd(),outbuf))
4977 exit_server("reply_writebmpx: send_smb failed.");
4979 /* Now the secondary */
4980 outsize = set_message(outbuf,1,0,True);
4981 SCVAL(outbuf,smb_com,SMBwritec);
4982 SSVAL(outbuf,smb_vwv0,nwritten);
4985 END_PROFILE(SMBwriteBmpx);
4989 /****************************************************************************
4990 Reply to a SMBwritebs (write block multiplex secondary) request.
4991 ****************************************************************************/
4993 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4996 ssize_t nwritten = -1;
5003 write_bmpx_struct *wbms;
5004 BOOL send_response = False;
5005 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5006 START_PROFILE(SMBwriteBs);
5008 CHECK_FSP(fsp,conn);
5011 tcount = SVAL(inbuf,smb_vwv1);
5012 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5013 numtowrite = SVAL(inbuf,smb_vwv6);
5014 smb_doff = SVAL(inbuf,smb_vwv7);
5016 data = smb_base(inbuf) + smb_doff;
5018 /* We need to send an SMBwriteC response, not an SMBwritebs */
5019 SCVAL(outbuf,smb_com,SMBwritec);
5021 /* This fd should have an auxiliary struct attached,
5022 check that it does */
5023 wbms = fsp->wbmpx_ptr;
5025 END_PROFILE(SMBwriteBs);
5029 /* If write through is set we can return errors, else we must cache them */
5030 write_through = wbms->wr_mode;
5032 /* Check for an earlier error */
5033 if(wbms->wr_discard) {
5034 END_PROFILE(SMBwriteBs);
5035 return -1; /* Just discard the packet */
5038 nwritten = write_file(fsp,data,startpos,numtowrite);
5040 if(lp_syncalways(SNUM(conn)) || write_through)
5041 sync_file(conn,fsp);
5043 if (nwritten < (ssize_t)numtowrite) {
5045 /* We are returning an error - we can delete the aux struct */
5048 fsp->wbmpx_ptr = NULL;
5049 END_PROFILE(SMBwriteBs);
5050 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5052 END_PROFILE(SMBwriteBs);
5053 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5056 /* Increment the total written, if this matches tcount
5057 we can discard the auxiliary struct (hurrah !) and return a writeC */
5058 wbms->wr_total_written += nwritten;
5059 if(wbms->wr_total_written >= tcount) {
5060 if (write_through) {
5061 outsize = set_message(outbuf,1,0,True);
5062 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5063 send_response = True;
5067 fsp->wbmpx_ptr = NULL;
5071 END_PROFILE(SMBwriteBs);
5075 END_PROFILE(SMBwriteBs);
5079 /****************************************************************************
5080 Reply to a SMBgetattrE.
5081 ****************************************************************************/
5083 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5085 SMB_STRUCT_STAT sbuf;
5088 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5089 START_PROFILE(SMBgetattrE);
5091 outsize = set_message(outbuf,11,0,True);
5093 if(!fsp || (fsp->conn != conn)) {
5094 END_PROFILE(SMBgetattrE);
5095 return ERROR_DOS(ERRDOS,ERRbadfid);
5098 /* Do an fstat on this file */
5099 if(fsp_stat(fsp, &sbuf)) {
5100 END_PROFILE(SMBgetattrE);
5101 return(UNIXERROR(ERRDOS,ERRnoaccess));
5104 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5107 * Convert the times into dos times. Set create
5108 * date to be last modify date as UNIX doesn't save
5112 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5113 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5114 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5117 SIVAL(outbuf,smb_vwv6,0);
5118 SIVAL(outbuf,smb_vwv8,0);
5120 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5121 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5122 SIVAL(outbuf,smb_vwv8,allocation_size);
5124 SSVAL(outbuf,smb_vwv10, mode);
5126 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5128 END_PROFILE(SMBgetattrE);