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 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
903 END_PROFILE(SMBsearch);
904 return ERROR_DOS(ERRDOS,ERRnomem);
907 dirtype = dptr_attr(dptr_num);
910 DEBUG(4,("dptr_num is %d\n",dptr_num));
913 if ((dirtype&0x1F) == aVOLID) {
915 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
916 dptr_fill(p+12,dptr_num);
917 if (dptr_zero(p+12) && (status_len==0))
921 p += DIR_STRUCT_SIZE;
924 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
926 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
927 conn->dirpath,lp_dontdescend(SNUM(conn))));
928 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
929 check_descend = True;
931 for (i=numentries;(i<maxentries) && !finished;i++) {
932 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
935 make_dir_struct(p,mask,fname,size,mode,date);
936 dptr_fill(p+12,dptr_num);
938 p += DIR_STRUCT_SIZE;
948 /* If we were called as SMBffirst with smb_search_id == NULL
949 and no entries were found then return error and close dirptr
952 if (numentries == 0 || !ok) {
953 dptr_close(&dptr_num);
954 } else if(ok && expect_close && status_len == 0) {
955 /* Close the dptr - we know it's gone */
956 dptr_close(&dptr_num);
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);
964 if ((numentries == 0) && !ms_has_wild(mask)) {
965 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
968 SSVAL(outbuf,smb_vwv0,numentries);
969 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
970 SCVAL(smb_buf(outbuf),0,5);
971 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
973 if (Protocol >= PROTOCOL_NT1)
974 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
976 outsize += DIR_STRUCT_SIZE*numentries;
977 smb_setlen(outbuf,outsize - 4);
979 if ((! *directory) && dptr_path(dptr_num))
980 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
982 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
983 smb_fn_name(CVAL(inbuf,smb_com)),
984 mask, directory, dirtype, numentries, maxentries ) );
986 END_PROFILE(SMBsearch);
990 /****************************************************************************
991 Reply to a fclose (stop directory search).
992 ****************************************************************************/
994 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1004 START_PROFILE(SMBfclose);
1006 outsize = set_message(outbuf,1,0,True);
1007 p = smb_buf(inbuf) + 1;
1008 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1009 if (!NT_STATUS_IS_OK(err)) {
1010 END_PROFILE(SMBfclose);
1011 return ERROR_NT(err);
1014 status_len = SVAL(p,0);
1017 if (status_len == 0) {
1018 END_PROFILE(SMBfclose);
1019 return ERROR_DOS(ERRSRV,ERRsrverror);
1022 memcpy(status,p,21);
1024 if(dptr_fetch(status+12,&dptr_num)) {
1025 /* Close the dptr - we know it's gone */
1026 dptr_close(&dptr_num);
1029 SSVAL(outbuf,smb_vwv0,0);
1031 DEBUG(3,("search close\n"));
1033 END_PROFILE(SMBfclose);
1037 /****************************************************************************
1039 ****************************************************************************/
1041 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1050 SMB_STRUCT_STAT sbuf;
1051 BOOL bad_path = False;
1053 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1054 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1056 START_PROFILE(SMBopen);
1058 share_mode = SVAL(inbuf,smb_vwv0);
1060 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 END_PROFILE(SMBopen);
1063 return ERROR_NT(status);
1066 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1068 unix_convert(fname,conn,0,&bad_path,&sbuf);
1070 END_PROFILE(SMBopen);
1071 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1074 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1075 (uint32)dos_attr, oplock_request,&rmode,NULL);
1078 END_PROFILE(SMBopen);
1079 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1080 /* We have re-scheduled this call. */
1081 clear_cached_errors();
1084 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1087 size = sbuf.st_size;
1088 fmode = dos_mode(conn,fname,&sbuf);
1089 mtime = sbuf.st_mtime;
1092 DEBUG(3,("attempt to open a directory %s\n",fname));
1093 close_file(fsp,False);
1094 END_PROFILE(SMBopen);
1095 return ERROR_DOS(ERRDOS,ERRnoaccess);
1098 outsize = set_message(outbuf,7,0,True);
1099 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1100 SSVAL(outbuf,smb_vwv1,fmode);
1101 if(lp_dos_filetime_resolution(SNUM(conn)) )
1102 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1104 put_dos_date3(outbuf,smb_vwv2,mtime);
1105 SIVAL(outbuf,smb_vwv4,(uint32)size);
1106 SSVAL(outbuf,smb_vwv6,rmode);
1108 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1109 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1111 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1112 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1113 END_PROFILE(SMBopen);
1117 /****************************************************************************
1118 Reply to an open and X.
1119 ****************************************************************************/
1121 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1124 int smb_mode = SVAL(inbuf,smb_vwv3);
1125 int smb_attr = SVAL(inbuf,smb_vwv5);
1126 /* Breakout the oplock request bits so we can set the
1127 reply bits separately. */
1128 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1129 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1130 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1132 int open_flags = SVAL(inbuf,smb_vwv2);
1133 int smb_sattr = SVAL(inbuf,smb_vwv4);
1134 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1136 int smb_ofun = SVAL(inbuf,smb_vwv8);
1138 int fmode=0,mtime=0,rmode=0;
1139 SMB_STRUCT_STAT sbuf;
1141 BOOL bad_path = False;
1144 START_PROFILE(SMBopenX);
1146 /* If it's an IPC, pass off the pipe handler. */
1148 if (lp_nt_pipe_support()) {
1149 END_PROFILE(SMBopenX);
1150 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1152 END_PROFILE(SMBopenX);
1153 return ERROR_DOS(ERRSRV,ERRaccess);
1157 /* XXXX we need to handle passed times, sattr and flags */
1158 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1159 if (!NT_STATUS_IS_OK(status)) {
1160 END_PROFILE(SMBopenX);
1161 return ERROR_NT(status);
1164 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1166 unix_convert(fname,conn,0,&bad_path,&sbuf);
1168 END_PROFILE(SMBopenX);
1169 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1172 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1173 oplock_request, &rmode,&smb_action);
1176 END_PROFILE(SMBopenX);
1177 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1178 /* We have re-scheduled this call. */
1179 clear_cached_errors();
1182 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1185 size = sbuf.st_size;
1186 fmode = dos_mode(conn,fname,&sbuf);
1187 mtime = sbuf.st_mtime;
1189 close_file(fsp,False);
1190 END_PROFILE(SMBopenX);
1191 return ERROR_DOS(ERRDOS,ERRnoaccess);
1194 /* If the caller set the extended oplock request bit
1195 and we granted one (by whatever means) - set the
1196 correct bit for extended oplock reply.
1199 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1200 smb_action |= EXTENDED_OPLOCK_GRANTED;
1202 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1203 smb_action |= EXTENDED_OPLOCK_GRANTED;
1205 /* If the caller set the core oplock request bit
1206 and we granted one (by whatever means) - set the
1207 correct bit for core oplock reply.
1210 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1211 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1213 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1214 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1216 set_message(outbuf,15,0,True);
1217 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1218 SSVAL(outbuf,smb_vwv3,fmode);
1219 if(lp_dos_filetime_resolution(SNUM(conn)) )
1220 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1222 put_dos_date3(outbuf,smb_vwv4,mtime);
1223 SIVAL(outbuf,smb_vwv6,(uint32)size);
1224 SSVAL(outbuf,smb_vwv8,rmode);
1225 SSVAL(outbuf,smb_vwv11,smb_action);
1227 END_PROFILE(SMBopenX);
1228 return chain_reply(inbuf,outbuf,length,bufsize);
1231 /****************************************************************************
1232 Reply to a SMBulogoffX.
1233 ****************************************************************************/
1235 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1237 uint16 vuid = SVAL(inbuf,smb_uid);
1238 user_struct *vuser = get_valid_user_struct(vuid);
1239 START_PROFILE(SMBulogoffX);
1242 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1244 /* in user level security we are supposed to close any files
1245 open by this user */
1246 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1247 file_close_user(vuid);
1249 invalidate_vuid(vuid);
1251 set_message(outbuf,2,0,True);
1253 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1255 END_PROFILE(SMBulogoffX);
1256 return chain_reply(inbuf,outbuf,length,bufsize);
1259 /****************************************************************************
1260 Reply to a mknew or a create.
1261 ****************************************************************************/
1263 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1270 BOOL bad_path = False;
1272 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1273 SMB_STRUCT_STAT sbuf;
1275 START_PROFILE(SMBcreate);
1277 com = SVAL(inbuf,smb_com);
1279 createmode = SVAL(inbuf,smb_vwv0);
1280 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 END_PROFILE(SMBcreate);
1283 return ERROR_NT(status);
1286 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1288 unix_convert(fname,conn,0,&bad_path,&sbuf);
1290 END_PROFILE(SMBcreate);
1291 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1294 if (createmode & aVOLID)
1295 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1297 if(com == SMBmknew) {
1298 /* We should fail if file exists. */
1299 ofun = FILE_CREATE_IF_NOT_EXIST;
1301 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1302 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1305 /* Open file in dos compatibility share mode. */
1306 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1307 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1310 END_PROFILE(SMBcreate);
1311 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1312 /* We have re-scheduled this call. */
1313 clear_cached_errors();
1316 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1319 outsize = set_message(outbuf,1,0,True);
1320 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1322 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1323 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1325 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1326 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1328 DEBUG( 2, ( "new file %s\n", fname ) );
1329 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1331 END_PROFILE(SMBcreate);
1335 /****************************************************************************
1336 Reply to a create temporary file.
1337 ****************************************************************************/
1339 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1344 BOOL bad_path = False;
1346 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1348 SMB_STRUCT_STAT sbuf;
1351 unsigned int namelen;
1353 START_PROFILE(SMBctemp);
1355 createattr = SVAL(inbuf,smb_vwv0);
1356 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 END_PROFILE(SMBctemp);
1359 return ERROR_NT(status);
1362 pstrcat(fname,"/TMXXXXXX");
1364 pstrcat(fname,"TMXXXXXX");
1367 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1369 unix_convert(fname,conn,0,&bad_path,&sbuf);
1371 END_PROFILE(SMBctemp);
1372 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1375 tmpfd = smb_mkstemp(fname);
1377 END_PROFILE(SMBctemp);
1378 return(UNIXERROR(ERRDOS,ERRnoaccess));
1381 SMB_VFS_STAT(conn,fname,&sbuf);
1383 /* Open file in dos compatibility share mode. */
1384 /* We should fail if file does not exist. */
1385 fsp = open_file_shared(conn,fname,&sbuf,
1386 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1387 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1388 (uint32)createattr, oplock_request, NULL, NULL);
1390 /* close fd from smb_mkstemp() */
1394 END_PROFILE(SMBctemp);
1395 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1396 /* We have re-scheduled this call. */
1397 clear_cached_errors();
1400 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1403 outsize = set_message(outbuf,1,0,True);
1404 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1406 /* the returned filename is relative to the directory */
1407 s = strrchr_m(fname, '/');
1413 p = smb_buf(outbuf);
1415 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1416 thing in the byte section. JRA */
1417 SSVALS(p, 0, -1); /* what is this? not in spec */
1419 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1421 outsize = set_message_end(outbuf, p);
1423 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1424 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1426 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1427 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1429 DEBUG( 2, ( "created temp file %s\n", fname ) );
1430 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1431 fname, fsp->fd, sbuf.st_mode ) );
1433 END_PROFILE(SMBctemp);
1437 /*******************************************************************
1438 Check if a user is allowed to rename a file.
1439 ********************************************************************/
1441 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1448 if (!CAN_WRITE(conn))
1449 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1451 fmode = dos_mode(conn,fname,pst);
1452 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1453 return NT_STATUS_NO_SUCH_FILE;
1455 if (S_ISDIR(pst->st_mode))
1456 return NT_STATUS_OK;
1458 /* We need a better way to return NT status codes from open... */
1462 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1463 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1466 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1467 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1468 ret = NT_STATUS_SHARING_VIOLATION;
1471 unix_ERR_ntstatus = NT_STATUS_OK;
1474 close_file(fsp,False);
1475 return NT_STATUS_OK;
1478 /*******************************************************************
1479 Check if a user is allowed to delete a file.
1480 ********************************************************************/
1482 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1484 SMB_STRUCT_STAT sbuf;
1490 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1493 if (!CAN_WRITE(conn))
1494 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1496 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1497 if(errno == ENOENT) {
1499 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1501 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1503 return map_nt_error_from_unix(errno);
1506 fmode = dos_mode(conn,fname,&sbuf);
1508 /* Can't delete a directory. */
1510 return NT_STATUS_FILE_IS_A_DIRECTORY;
1512 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1513 return NT_STATUS_OBJECT_NAME_INVALID;
1514 #endif /* JRATEST */
1516 if (!lp_delete_readonly(SNUM(conn))) {
1518 return NT_STATUS_CANNOT_DELETE;
1520 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1521 return NT_STATUS_NO_SUCH_FILE;
1523 if (check_is_at_open) {
1524 if (!can_delete_file_in_directory(conn, fname)) {
1525 return NT_STATUS_ACCESS_DENIED;
1528 /* On open checks the open itself will check the share mode, so
1529 don't do it here as we'll get it wrong. */
1531 /* We need a better way to return NT status codes from open... */
1535 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1536 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1539 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1540 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1541 ret = unix_ERR_ntstatus;
1542 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1543 ret = NT_STATUS_SHARING_VIOLATION;
1546 unix_ERR_ntstatus = NT_STATUS_OK;
1549 close_file(fsp,False);
1551 return NT_STATUS_OK;
1554 /****************************************************************************
1555 The guts of the unlink command, split out so it may be called by the NT SMB
1557 ****************************************************************************/
1559 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1565 NTSTATUS error = NT_STATUS_OK;
1567 BOOL bad_path = False;
1569 SMB_STRUCT_STAT sbuf;
1571 *directory = *mask = 0;
1573 /* We must check for wildcards in the name given
1574 * directly by the client - before any unmangling.
1575 * This prevents an unmangling of a UNIX name containing
1576 * a DOS wildcard like '*' or '?' from unmangling into
1577 * a wildcard delete which was not intended.
1578 * FIX for #226. JRA.
1581 has_wild = ms_has_wild(name);
1583 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1585 p = strrchr_m(name,'/');
1587 pstrcpy(directory,".");
1591 pstrcpy(directory,name);
1596 * We should only check the mangled cache
1597 * here if unix_convert failed. This means
1598 * that the path in 'mask' doesn't exist
1599 * on the file system and so we need to look
1600 * for a possible mangle. This patch from
1601 * Tine Smukavec <valentin.smukavec@hermes.si>.
1604 if (!rc && mangle_is_mangled(mask))
1605 mangle_check_cache( mask, sizeof(pstring)-1 );
1608 pstrcat(directory,"/");
1609 pstrcat(directory,mask);
1610 error = can_delete(conn,directory,dirtype,bad_path,False);
1611 if (!NT_STATUS_IS_OK(error))
1614 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1618 struct smb_Dir *dir_hnd = NULL;
1621 if (check_name(directory,conn))
1622 dir_hnd = OpenDir(conn, directory);
1624 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1625 the pattern matches against the long name, otherwise the short name
1626 We don't implement this yet XXXX
1631 error = NT_STATUS_NO_SUCH_FILE;
1633 if (strequal(mask,"????????.???"))
1636 while ((dname = ReadDirName(dir_hnd, &offset))) {
1639 BOOL sys_direntry = False;
1640 pstrcpy(fname,dname);
1642 if (!is_visible_file(conn, directory, dname, &st, True)) {
1646 /* Quick check for "." and ".." */
1647 if (fname[0] == '.') {
1648 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1649 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1650 sys_direntry = True;
1657 if(!mask_match(fname, mask, conn->case_sensitive))
1661 error = NT_STATUS_OBJECT_NAME_INVALID;
1662 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1667 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1668 error = can_delete(conn,fname,dirtype,bad_path,False);
1669 if (!NT_STATUS_IS_OK(error)) {
1672 if (SMB_VFS_UNLINK(conn,fname) == 0)
1674 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1680 if (count == 0 && NT_STATUS_IS_OK(error)) {
1681 error = map_nt_error_from_unix(errno);
1687 /****************************************************************************
1689 ****************************************************************************/
1691 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1698 START_PROFILE(SMBunlink);
1700 dirtype = SVAL(inbuf,smb_vwv0);
1702 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 END_PROFILE(SMBunlink);
1705 return ERROR_NT(status);
1708 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1710 DEBUG(3,("reply_unlink : %s\n",name));
1712 status = unlink_internals(conn, dirtype, name);
1713 if (!NT_STATUS_IS_OK(status)) {
1714 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1715 /* We have re-scheduled this call. */
1716 clear_cached_errors();
1719 return ERROR_NT(status);
1723 * Win2k needs a changenotify request response before it will
1724 * update after a rename..
1726 process_pending_change_notify_queue((time_t)0);
1728 outsize = set_message(outbuf,0,0,True);
1730 END_PROFILE(SMBunlink);
1734 /****************************************************************************
1736 ****************************************************************************/
1738 static void fail_readraw(void)
1741 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1743 exit_server(errstr);
1746 #if defined(WITH_SENDFILE)
1747 /****************************************************************************
1748 Fake (read/write) sendfile. Returns -1 on read or write fail.
1749 ****************************************************************************/
1751 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1755 /* Paranioa check... */
1756 if (nread > bufsize) {
1761 ret = read_file(fsp,buf,startpos,nread);
1767 /* If we had a short read, fill with zeros. */
1769 memset(buf, '\0', nread - ret);
1772 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1776 return (ssize_t)nread;
1780 /****************************************************************************
1781 Use sendfile in readbraw.
1782 ****************************************************************************/
1784 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1785 ssize_t mincount, char *outbuf, int out_buffsize)
1789 #if defined(WITH_SENDFILE)
1791 * We can only use sendfile on a non-chained packet
1792 * but we can use on a non-oplocked file. tridge proved this
1793 * on a train in Germany :-). JRA.
1794 * reply_readbraw has already checked the length.
1797 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1800 _smb_setlen(outbuf,nread);
1801 header.data = outbuf;
1805 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1806 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1807 if (errno == ENOSYS) {
1808 goto normal_readbraw;
1812 * Special hack for broken Linux with no working sendfile. If we
1813 * return EINTR we sent the header but not the rest of the data.
1814 * Fake this up by doing read/write calls.
1816 if (errno == EINTR) {
1817 /* Ensure we don't do this again. */
1818 set_use_sendfile(SNUM(conn), False);
1819 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1821 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1822 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1823 fsp->fsp_name, strerror(errno) ));
1824 exit_server("send_file_readbraw fake_sendfile failed");
1829 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1830 fsp->fsp_name, strerror(errno) ));
1831 exit_server("send_file_readbraw sendfile failed");
1841 ret = read_file(fsp,outbuf+4,startpos,nread);
1842 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1851 _smb_setlen(outbuf,ret);
1852 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1856 /****************************************************************************
1857 Reply to a readbraw (core+ protocol).
1858 ****************************************************************************/
1860 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1862 extern struct current_user current_user;
1863 ssize_t maxcount,mincount;
1866 char *header = outbuf;
1868 START_PROFILE(SMBreadbraw);
1870 if (srv_is_signing_active()) {
1871 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1875 * Special check if an oplock break has been issued
1876 * and the readraw request croses on the wire, we must
1877 * return a zero length response here.
1880 if(global_oplock_break) {
1881 _smb_setlen(header,0);
1882 if (write_data(smbd_server_fd(),header,4) != 4)
1884 DEBUG(5,("readbraw - oplock break finished\n"));
1885 END_PROFILE(SMBreadbraw);
1889 fsp = file_fsp(inbuf,smb_vwv0);
1891 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1893 * fsp could be NULL here so use the value from the packet. JRA.
1895 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1896 _smb_setlen(header,0);
1897 if (write_data(smbd_server_fd(),header,4) != 4)
1899 END_PROFILE(SMBreadbraw);
1903 CHECK_FSP(fsp,conn);
1905 flush_write_cache(fsp, READRAW_FLUSH);
1907 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1908 if(CVAL(inbuf,smb_wct) == 10) {
1910 * This is a large offset (64 bit) read.
1912 #ifdef LARGE_SMB_OFF_T
1914 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1916 #else /* !LARGE_SMB_OFF_T */
1919 * Ensure we haven't been sent a >32 bit offset.
1922 if(IVAL(inbuf,smb_vwv8) != 0) {
1923 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1924 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1925 _smb_setlen(header,0);
1926 if (write_data(smbd_server_fd(),header,4) != 4)
1928 END_PROFILE(SMBreadbraw);
1932 #endif /* LARGE_SMB_OFF_T */
1935 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1936 _smb_setlen(header,0);
1937 if (write_data(smbd_server_fd(),header,4) != 4)
1939 END_PROFILE(SMBreadbraw);
1943 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1944 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1946 /* ensure we don't overrun the packet size */
1947 maxcount = MIN(65535,maxcount);
1949 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
1950 SMB_OFF_T size = fsp->size;
1951 SMB_OFF_T sizeneeded = startpos + maxcount;
1953 if (size < sizeneeded) {
1955 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1957 if (!fsp->can_write)
1961 if (startpos >= size)
1964 nread = MIN(maxcount,(size - startpos));
1967 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1968 if (nread < mincount)
1972 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1973 (int)maxcount, (int)mincount, (int)nread ) );
1975 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
1977 DEBUG(5,("readbraw finished\n"));
1978 END_PROFILE(SMBreadbraw);
1982 /****************************************************************************
1983 Reply to a lockread (core+ protocol).
1984 ****************************************************************************/
1986 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1994 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1995 BOOL my_lock_ctx = False;
1996 START_PROFILE(SMBlockread);
1998 CHECK_FSP(fsp,conn);
2001 release_level_2_oplocks_on_change(fsp);
2003 numtoread = SVAL(inbuf,smb_vwv1);
2004 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2006 outsize = set_message(outbuf,5,3,True);
2007 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2008 data = smb_buf(outbuf) + 3;
2011 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2012 * protocol request that predates the read/write lock concept.
2013 * Thus instead of asking for a read lock here we need to ask
2014 * for a write lock. JRA.
2015 * Note that the requested lock size is unaffected by max_recv.
2018 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2019 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2021 if (NT_STATUS_V(status)) {
2024 * We used to make lockread a blocking lock. It turns out
2025 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2029 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2031 * A blocking lock was requested. Package up
2032 * this smb into a queued request and push it
2033 * onto the blocking lock queue.
2035 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2036 (SMB_BIG_UINT)numtoread)) {
2037 END_PROFILE(SMBlockread);
2042 END_PROFILE(SMBlockread);
2043 return ERROR_NT(status);
2047 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2050 if (numtoread > max_recv) {
2051 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2052 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2053 (unsigned int)numtoread, (unsigned int)max_recv ));
2054 numtoread = MIN(numtoread,max_recv);
2056 nread = read_file(fsp,data,startpos,numtoread);
2059 END_PROFILE(SMBlockread);
2060 return(UNIXERROR(ERRDOS,ERRnoaccess));
2064 SSVAL(outbuf,smb_vwv0,nread);
2065 SSVAL(outbuf,smb_vwv5,nread+3);
2066 SSVAL(smb_buf(outbuf),1,nread);
2068 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2069 fsp->fnum, (int)numtoread, (int)nread));
2071 END_PROFILE(SMBlockread);
2075 /****************************************************************************
2077 ****************************************************************************/
2079 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2086 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2087 START_PROFILE(SMBread);
2089 CHECK_FSP(fsp,conn);
2092 numtoread = SVAL(inbuf,smb_vwv1);
2093 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2095 outsize = set_message(outbuf,5,3,True);
2096 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2098 * The requested read size cannot be greater than max_recv. JRA.
2100 if (numtoread > max_recv) {
2101 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2102 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2103 (unsigned int)numtoread, (unsigned int)max_recv ));
2104 numtoread = MIN(numtoread,max_recv);
2107 data = smb_buf(outbuf) + 3;
2109 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2110 END_PROFILE(SMBread);
2111 return ERROR_DOS(ERRDOS,ERRlock);
2115 nread = read_file(fsp,data,startpos,numtoread);
2118 END_PROFILE(SMBread);
2119 return(UNIXERROR(ERRDOS,ERRnoaccess));
2123 SSVAL(outbuf,smb_vwv0,nread);
2124 SSVAL(outbuf,smb_vwv5,nread+3);
2125 SCVAL(smb_buf(outbuf),0,1);
2126 SSVAL(smb_buf(outbuf),1,nread);
2128 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2129 fsp->fnum, (int)numtoread, (int)nread ) );
2131 END_PROFILE(SMBread);
2135 /****************************************************************************
2136 Reply to a read and X - possibly using sendfile.
2137 ****************************************************************************/
2139 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2140 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2144 char *data = smb_buf(outbuf);
2146 #if defined(WITH_SENDFILE)
2148 * We can only use sendfile on a non-chained packet
2149 * but we can use on a non-oplocked file. tridge proved this
2150 * on a train in Germany :-). JRA.
2153 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2154 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2155 SMB_STRUCT_STAT sbuf;
2158 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2159 return(UNIXERROR(ERRDOS,ERRnoaccess));
2161 if (startpos > sbuf.st_size)
2164 if (smb_maxcnt > (sbuf.st_size - startpos))
2165 smb_maxcnt = (sbuf.st_size - startpos);
2167 if (smb_maxcnt == 0)
2171 * Set up the packet header before send. We
2172 * assume here the sendfile will work (get the
2173 * correct amount of data).
2176 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2177 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2178 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2179 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2180 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2181 SCVAL(outbuf,smb_vwv0,0xFF);
2182 set_message(outbuf,12,smb_maxcnt,False);
2183 header.data = outbuf;
2184 header.length = data - outbuf;
2187 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2188 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2189 if (errno == ENOSYS) {
2194 * Special hack for broken Linux with no working sendfile. If we
2195 * return EINTR we sent the header but not the rest of the data.
2196 * Fake this up by doing read/write calls.
2199 if (errno == EINTR) {
2200 /* Ensure we don't do this again. */
2201 set_use_sendfile(SNUM(conn), False);
2202 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2204 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2205 len_outbuf - (data-outbuf))) == -1) {
2206 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2207 fsp->fsp_name, strerror(errno) ));
2208 exit_server("send_file_readX: fake_sendfile failed");
2210 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2211 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2212 /* Returning -1 here means successful sendfile. */
2216 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2217 fsp->fsp_name, strerror(errno) ));
2218 exit_server("send_file_readX sendfile failed");
2221 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2222 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2223 /* Returning -1 here means successful sendfile. */
2231 nread = read_file(fsp,data,startpos,smb_maxcnt);
2234 END_PROFILE(SMBreadX);
2235 return(UNIXERROR(ERRDOS,ERRnoaccess));
2238 outsize = set_message(outbuf,12,nread,False);
2239 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2240 SSVAL(outbuf,smb_vwv5,nread);
2241 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2242 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2243 SSVAL(smb_buf(outbuf),-2,nread);
2245 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2246 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2248 /* Returning the number of bytes we want to send back - including header. */
2252 /****************************************************************************
2253 Reply to a read and X.
2254 ****************************************************************************/
2256 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2258 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2259 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2261 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2263 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2266 START_PROFILE(SMBreadX);
2268 /* If it's an IPC, pass off the pipe handler. */
2270 END_PROFILE(SMBreadX);
2271 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2274 CHECK_FSP(fsp,conn);
2277 set_message(outbuf,12,0,True);
2279 if (global_client_caps & CAP_LARGE_READX) {
2280 if (SVAL(inbuf,smb_vwv7) == 1) {
2281 smb_maxcnt |= (1<<16);
2283 if (smb_maxcnt > BUFFER_SIZE) {
2284 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2285 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2286 END_PROFILE(SMBreadX);
2287 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2291 if(CVAL(inbuf,smb_wct) == 12) {
2292 #ifdef LARGE_SMB_OFF_T
2294 * This is a large offset (64 bit) read.
2296 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2298 #else /* !LARGE_SMB_OFF_T */
2301 * Ensure we haven't been sent a >32 bit offset.
2304 if(IVAL(inbuf,smb_vwv10) != 0) {
2305 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2306 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2307 END_PROFILE(SMBreadX);
2308 return ERROR_DOS(ERRDOS,ERRbadaccess);
2311 #endif /* LARGE_SMB_OFF_T */
2315 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2316 END_PROFILE(SMBreadX);
2317 return ERROR_DOS(ERRDOS,ERRlock);
2320 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2322 nread = chain_reply(inbuf,outbuf,length,bufsize);
2324 END_PROFILE(SMBreadX);
2328 /****************************************************************************
2329 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2330 ****************************************************************************/
2332 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2335 ssize_t total_written=0;
2336 size_t numtowrite=0;
2341 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2343 START_PROFILE(SMBwritebraw);
2345 if (srv_is_signing_active()) {
2346 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2349 CHECK_FSP(fsp,conn);
2352 tcount = IVAL(inbuf,smb_vwv1);
2353 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2354 write_through = BITSETW(inbuf+smb_vwv7,0);
2356 /* We have to deal with slightly different formats depending
2357 on whether we are using the core+ or lanman1.0 protocol */
2359 if(Protocol <= PROTOCOL_COREPLUS) {
2360 numtowrite = SVAL(smb_buf(inbuf),-2);
2361 data = smb_buf(inbuf);
2363 numtowrite = SVAL(inbuf,smb_vwv10);
2364 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2367 /* force the error type */
2368 SCVAL(inbuf,smb_com,SMBwritec);
2369 SCVAL(outbuf,smb_com,SMBwritec);
2371 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2372 END_PROFILE(SMBwritebraw);
2373 return(ERROR_DOS(ERRDOS,ERRlock));
2377 nwritten = write_file(fsp,data,startpos,numtowrite);
2379 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2380 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2382 if (nwritten < (ssize_t)numtowrite) {
2383 END_PROFILE(SMBwritebraw);
2384 return(UNIXERROR(ERRHRD,ERRdiskfull));
2387 total_written = nwritten;
2389 /* Return a message to the redirector to tell it to send more bytes */
2390 SCVAL(outbuf,smb_com,SMBwritebraw);
2391 SSVALS(outbuf,smb_vwv0,-1);
2392 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2393 if (!send_smb(smbd_server_fd(),outbuf))
2394 exit_server("reply_writebraw: send_smb failed.");
2396 /* Now read the raw data into the buffer and write it */
2397 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2398 exit_server("secondary writebraw failed");
2401 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2402 numtowrite = smb_len(inbuf);
2404 /* Set up outbuf to return the correct return */
2405 outsize = set_message(outbuf,1,0,True);
2406 SCVAL(outbuf,smb_com,SMBwritec);
2407 SSVAL(outbuf,smb_vwv0,total_written);
2409 if (numtowrite != 0) {
2411 if (numtowrite > BUFFER_SIZE) {
2412 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2413 (unsigned int)numtowrite ));
2414 exit_server("secondary writebraw failed");
2417 if (tcount > nwritten+numtowrite) {
2418 DEBUG(3,("Client overestimated the write %d %d %d\n",
2419 (int)tcount,(int)nwritten,(int)numtowrite));
2422 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2423 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2425 exit_server("secondary writebraw failed");
2428 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2430 if (nwritten < (ssize_t)numtowrite) {
2431 SCVAL(outbuf,smb_rcls,ERRHRD);
2432 SSVAL(outbuf,smb_err,ERRdiskfull);
2436 total_written += nwritten;
2439 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2440 sync_file(conn,fsp);
2442 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2443 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2445 /* we won't return a status if write through is not selected - this follows what WfWg does */
2446 END_PROFILE(SMBwritebraw);
2447 if (!write_through && total_written==tcount) {
2449 #if RABBIT_PELLET_FIX
2451 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2452 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2454 if (!send_keepalive(smbd_server_fd()))
2455 exit_server("reply_writebraw: send of keepalive failed");
2463 /****************************************************************************
2464 Reply to a writeunlock (core+).
2465 ****************************************************************************/
2467 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2468 int size, int dum_buffsize)
2470 ssize_t nwritten = -1;
2474 NTSTATUS status = NT_STATUS_OK;
2475 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2477 START_PROFILE(SMBwriteunlock);
2479 CHECK_FSP(fsp,conn);
2482 numtowrite = SVAL(inbuf,smb_vwv1);
2483 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2484 data = smb_buf(inbuf) + 3;
2486 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2487 END_PROFILE(SMBwriteunlock);
2488 return ERROR_DOS(ERRDOS,ERRlock);
2491 /* The special X/Open SMB protocol handling of
2492 zero length writes is *NOT* done for
2497 nwritten = write_file(fsp,data,startpos,numtowrite);
2499 if (lp_syncalways(SNUM(conn)))
2500 sync_file(conn,fsp);
2502 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2503 END_PROFILE(SMBwriteunlock);
2504 return(UNIXERROR(ERRHRD,ERRdiskfull));
2508 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2509 (SMB_BIG_UINT)startpos);
2510 if (NT_STATUS_V(status)) {
2511 END_PROFILE(SMBwriteunlock);
2512 return ERROR_NT(status);
2516 outsize = set_message(outbuf,1,0,True);
2518 SSVAL(outbuf,smb_vwv0,nwritten);
2520 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2521 fsp->fnum, (int)numtowrite, (int)nwritten));
2523 END_PROFILE(SMBwriteunlock);
2527 /****************************************************************************
2529 ****************************************************************************/
2531 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2534 ssize_t nwritten = -1;
2537 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2539 START_PROFILE(SMBwrite);
2541 /* If it's an IPC, pass off the pipe handler. */
2543 END_PROFILE(SMBwrite);
2544 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2547 CHECK_FSP(fsp,conn);
2550 numtowrite = SVAL(inbuf,smb_vwv1);
2551 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2552 data = smb_buf(inbuf) + 3;
2554 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2555 END_PROFILE(SMBwrite);
2556 return ERROR_DOS(ERRDOS,ERRlock);
2560 * X/Open SMB protocol says that if smb_vwv1 is
2561 * zero then the file size should be extended or
2562 * truncated to the size given in smb_vwv[2-3].
2565 if(numtowrite == 0) {
2567 * This is actually an allocate call, and set EOF. JRA.
2569 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2571 END_PROFILE(SMBwrite);
2572 return ERROR_NT(NT_STATUS_DISK_FULL);
2574 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2576 END_PROFILE(SMBwrite);
2577 return ERROR_NT(NT_STATUS_DISK_FULL);
2580 nwritten = write_file(fsp,data,startpos,numtowrite);
2582 if (lp_syncalways(SNUM(conn)))
2583 sync_file(conn,fsp);
2585 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2586 END_PROFILE(SMBwrite);
2587 return(UNIXERROR(ERRHRD,ERRdiskfull));
2590 outsize = set_message(outbuf,1,0,True);
2592 SSVAL(outbuf,smb_vwv0,nwritten);
2594 if (nwritten < (ssize_t)numtowrite) {
2595 SCVAL(outbuf,smb_rcls,ERRHRD);
2596 SSVAL(outbuf,smb_err,ERRdiskfull);
2599 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2601 END_PROFILE(SMBwrite);
2605 /****************************************************************************
2606 Reply to a write and X.
2607 ****************************************************************************/
2609 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2611 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2612 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2613 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2614 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2615 ssize_t nwritten = -1;
2616 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2617 unsigned int smblen = smb_len(inbuf);
2619 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2620 START_PROFILE(SMBwriteX);
2622 /* If it's an IPC, pass off the pipe handler. */
2624 END_PROFILE(SMBwriteX);
2625 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2628 CHECK_FSP(fsp,conn);
2631 /* Deal with possible LARGE_WRITEX */
2633 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2635 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2636 END_PROFILE(SMBwriteX);
2637 return ERROR_DOS(ERRDOS,ERRbadmem);
2640 data = smb_base(inbuf) + smb_doff;
2642 if(CVAL(inbuf,smb_wct) == 14) {
2643 #ifdef LARGE_SMB_OFF_T
2645 * This is a large offset (64 bit) write.
2647 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2649 #else /* !LARGE_SMB_OFF_T */
2652 * Ensure we haven't been sent a >32 bit offset.
2655 if(IVAL(inbuf,smb_vwv12) != 0) {
2656 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2657 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2658 END_PROFILE(SMBwriteX);
2659 return ERROR_DOS(ERRDOS,ERRbadaccess);
2662 #endif /* LARGE_SMB_OFF_T */
2665 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2666 END_PROFILE(SMBwriteX);
2667 return ERROR_DOS(ERRDOS,ERRlock);
2670 /* X/Open SMB protocol says that, unlike SMBwrite
2671 if the length is zero then NO truncation is
2672 done, just a write of zero. To truncate a file,
2678 nwritten = write_file(fsp,data,startpos,numtowrite);
2680 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2681 END_PROFILE(SMBwriteX);
2682 return(UNIXERROR(ERRHRD,ERRdiskfull));
2685 set_message(outbuf,6,0,True);
2687 SSVAL(outbuf,smb_vwv2,nwritten);
2689 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2691 if (nwritten < (ssize_t)numtowrite) {
2692 SCVAL(outbuf,smb_rcls,ERRHRD);
2693 SSVAL(outbuf,smb_err,ERRdiskfull);
2696 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2697 fsp->fnum, (int)numtowrite, (int)nwritten));
2699 if (lp_syncalways(SNUM(conn)) || write_through)
2700 sync_file(conn,fsp);
2702 END_PROFILE(SMBwriteX);
2703 return chain_reply(inbuf,outbuf,length,bufsize);
2706 /****************************************************************************
2708 ****************************************************************************/
2710 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2716 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2717 START_PROFILE(SMBlseek);
2719 CHECK_FSP(fsp,conn);
2721 flush_write_cache(fsp, SEEK_FLUSH);
2723 mode = SVAL(inbuf,smb_vwv1) & 3;
2724 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2725 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2734 res = fsp->pos + startpos;
2745 if (umode == SEEK_END) {
2746 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2747 if(errno == EINVAL) {
2748 SMB_OFF_T current_pos = startpos;
2749 SMB_STRUCT_STAT sbuf;
2751 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2752 END_PROFILE(SMBlseek);
2753 return(UNIXERROR(ERRDOS,ERRnoaccess));
2756 current_pos += sbuf.st_size;
2758 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2763 END_PROFILE(SMBlseek);
2764 return(UNIXERROR(ERRDOS,ERRnoaccess));
2770 outsize = set_message(outbuf,2,0,True);
2771 SIVAL(outbuf,smb_vwv0,res);
2773 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2774 fsp->fnum, (double)startpos, (double)res, mode));
2776 END_PROFILE(SMBlseek);
2780 /****************************************************************************
2782 ****************************************************************************/
2784 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2786 int outsize = set_message(outbuf,0,0,True);
2787 uint16 fnum = SVAL(inbuf,smb_vwv0);
2788 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2789 START_PROFILE(SMBflush);
2792 CHECK_FSP(fsp,conn);
2795 file_sync_all(conn);
2797 sync_file(conn,fsp);
2800 DEBUG(3,("flush\n"));
2801 END_PROFILE(SMBflush);
2805 /****************************************************************************
2807 ****************************************************************************/
2809 int reply_exit(connection_struct *conn,
2810 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2813 START_PROFILE(SMBexit);
2815 file_close_pid(SVAL(inbuf,smb_pid));
2817 outsize = set_message(outbuf,0,0,True);
2819 DEBUG(3,("exit\n"));
2821 END_PROFILE(SMBexit);
2825 /****************************************************************************
2826 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2827 ****************************************************************************/
2829 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2832 extern struct current_user current_user;
2835 int32 eclass = 0, err = 0;
2836 files_struct *fsp = NULL;
2837 START_PROFILE(SMBclose);
2839 outsize = set_message(outbuf,0,0,True);
2841 /* If it's an IPC, pass off to the pipe handler. */
2843 END_PROFILE(SMBclose);
2844 return reply_pipe_close(conn, inbuf,outbuf);
2847 fsp = file_fsp(inbuf,smb_vwv0);
2850 * We can only use CHECK_FSP if we know it's not a directory.
2853 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2854 END_PROFILE(SMBclose);
2855 return ERROR_DOS(ERRDOS,ERRbadfid);
2858 if(fsp->is_directory) {
2860 * Special case - close NT SMB directory handle.
2862 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2863 close_file(fsp,True);
2866 * Close ordinary file.
2871 /* Save the name for time set in close. */
2872 pstrcpy( file_name, fsp->fsp_name);
2874 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2876 conn->num_files_open));
2879 * close_file() returns the unix errno if an error
2880 * was detected on close - normally this is due to
2881 * a disk full error. If not then it was probably an I/O error.
2884 if((close_err = close_file(fsp,True)) != 0) {
2886 END_PROFILE(SMBclose);
2887 return (UNIXERROR(ERRHRD,ERRgeneral));
2891 * Now take care of any time sent in the close.
2894 mtime = make_unix_date3(inbuf+smb_vwv1);
2896 /* try and set the date */
2897 set_filetime(conn, file_name, mtime);
2901 /* We have a cached error */
2903 END_PROFILE(SMBclose);
2904 return ERROR_DOS(eclass,err);
2907 END_PROFILE(SMBclose);
2911 /****************************************************************************
2912 Reply to a writeclose (Core+ protocol).
2913 ****************************************************************************/
2915 int reply_writeclose(connection_struct *conn,
2916 char *inbuf,char *outbuf, int size, int dum_buffsize)
2919 ssize_t nwritten = -1;
2925 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2926 START_PROFILE(SMBwriteclose);
2928 CHECK_FSP(fsp,conn);
2931 numtowrite = SVAL(inbuf,smb_vwv1);
2932 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2933 mtime = make_unix_date3(inbuf+smb_vwv4);
2934 data = smb_buf(inbuf) + 1;
2936 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2937 END_PROFILE(SMBwriteclose);
2938 return ERROR_DOS(ERRDOS,ERRlock);
2941 nwritten = write_file(fsp,data,startpos,numtowrite);
2943 set_filetime(conn, fsp->fsp_name,mtime);
2946 * More insanity. W2K only closes the file if writelen > 0.
2951 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2953 close_err = close_file(fsp,True);
2956 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2957 fsp->fnum, (int)numtowrite, (int)nwritten,
2958 conn->num_files_open));
2960 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2961 END_PROFILE(SMBwriteclose);
2962 return(UNIXERROR(ERRHRD,ERRdiskfull));
2965 if(close_err != 0) {
2967 END_PROFILE(SMBwriteclose);
2968 return(UNIXERROR(ERRHRD,ERRgeneral));
2971 outsize = set_message(outbuf,1,0,True);
2973 SSVAL(outbuf,smb_vwv0,nwritten);
2974 END_PROFILE(SMBwriteclose);
2978 /****************************************************************************
2980 ****************************************************************************/
2982 int reply_lock(connection_struct *conn,
2983 char *inbuf,char *outbuf, int length, int dum_buffsize)
2985 int outsize = set_message(outbuf,0,0,True);
2986 SMB_BIG_UINT count,offset;
2988 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2989 BOOL my_lock_ctx = False;
2991 START_PROFILE(SMBlock);
2993 CHECK_FSP(fsp,conn);
2995 release_level_2_oplocks_on_change(fsp);
2997 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2998 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3000 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3001 fsp->fd, fsp->fnum, (double)offset, (double)count));
3003 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3004 if (NT_STATUS_V(status)) {
3006 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3007 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3009 * A blocking lock was requested. Package up
3010 * this smb into a queued request and push it
3011 * onto the blocking lock queue.
3013 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3014 END_PROFILE(SMBlock);
3019 END_PROFILE(SMBlock);
3020 return ERROR_NT(status);
3023 END_PROFILE(SMBlock);
3027 /****************************************************************************
3029 ****************************************************************************/
3031 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3034 int outsize = set_message(outbuf,0,0,True);
3035 SMB_BIG_UINT count,offset;
3037 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3038 START_PROFILE(SMBunlock);
3040 CHECK_FSP(fsp,conn);
3042 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3043 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3045 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3046 if (NT_STATUS_V(status)) {
3047 END_PROFILE(SMBunlock);
3048 return ERROR_NT(status);
3051 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3052 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3054 END_PROFILE(SMBunlock);
3058 /****************************************************************************
3060 ****************************************************************************/
3062 int reply_tdis(connection_struct *conn,
3063 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3065 int outsize = set_message(outbuf,0,0,True);
3067 START_PROFILE(SMBtdis);
3069 vuid = SVAL(inbuf,smb_uid);
3072 DEBUG(4,("Invalid connection in tdis\n"));
3073 END_PROFILE(SMBtdis);
3074 return ERROR_DOS(ERRSRV,ERRinvnid);
3079 close_cnum(conn,vuid);
3081 END_PROFILE(SMBtdis);
3085 /****************************************************************************
3087 ****************************************************************************/
3089 int reply_echo(connection_struct *conn,
3090 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3092 int smb_reverb = SVAL(inbuf,smb_vwv0);
3094 unsigned int data_len = smb_buflen(inbuf);
3095 int outsize = set_message(outbuf,1,data_len,True);
3096 START_PROFILE(SMBecho);
3098 if (data_len > BUFFER_SIZE) {
3099 DEBUG(0,("reply_echo: data_len too large.\n"));
3100 END_PROFILE(SMBecho);
3104 /* copy any incoming data back out */
3106 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3108 if (smb_reverb > 100) {
3109 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3113 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3114 SSVAL(outbuf,smb_vwv0,seq_num);
3116 smb_setlen(outbuf,outsize - 4);
3118 if (!send_smb(smbd_server_fd(),outbuf))
3119 exit_server("reply_echo: send_smb failed.");
3122 DEBUG(3,("echo %d times\n", smb_reverb));
3126 END_PROFILE(SMBecho);
3130 /****************************************************************************
3131 Reply to a printopen.
3132 ****************************************************************************/
3134 int reply_printopen(connection_struct *conn,
3135 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3139 START_PROFILE(SMBsplopen);
3141 if (!CAN_PRINT(conn)) {
3142 END_PROFILE(SMBsplopen);
3143 return ERROR_DOS(ERRDOS,ERRnoaccess);
3146 /* Open for exclusive use, write only. */
3147 fsp = print_fsp_open(conn, NULL);
3150 END_PROFILE(SMBsplopen);
3151 return(UNIXERROR(ERRDOS,ERRnoaccess));
3154 outsize = set_message(outbuf,1,0,True);
3155 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3157 DEBUG(3,("openprint fd=%d fnum=%d\n",
3158 fsp->fd, fsp->fnum));
3160 END_PROFILE(SMBsplopen);
3164 /****************************************************************************
3165 Reply to a printclose.
3166 ****************************************************************************/
3168 int reply_printclose(connection_struct *conn,
3169 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3171 int outsize = set_message(outbuf,0,0,True);
3172 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3174 START_PROFILE(SMBsplclose);
3176 CHECK_FSP(fsp,conn);
3178 if (!CAN_PRINT(conn)) {
3179 END_PROFILE(SMBsplclose);
3180 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3183 DEBUG(3,("printclose fd=%d fnum=%d\n",
3184 fsp->fd,fsp->fnum));
3186 close_err = close_file(fsp,True);
3188 if(close_err != 0) {
3190 END_PROFILE(SMBsplclose);
3191 return(UNIXERROR(ERRHRD,ERRgeneral));
3194 END_PROFILE(SMBsplclose);
3198 /****************************************************************************
3199 Reply to a printqueue.
3200 ****************************************************************************/
3202 int reply_printqueue(connection_struct *conn,
3203 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3205 int outsize = set_message(outbuf,2,3,True);
3206 int max_count = SVAL(inbuf,smb_vwv0);
3207 int start_index = SVAL(inbuf,smb_vwv1);
3208 START_PROFILE(SMBsplretq);
3210 /* we used to allow the client to get the cnum wrong, but that
3211 is really quite gross and only worked when there was only
3212 one printer - I think we should now only accept it if they
3213 get it right (tridge) */
3214 if (!CAN_PRINT(conn)) {
3215 END_PROFILE(SMBsplretq);
3216 return ERROR_DOS(ERRDOS,ERRnoaccess);
3219 SSVAL(outbuf,smb_vwv0,0);
3220 SSVAL(outbuf,smb_vwv1,0);
3221 SCVAL(smb_buf(outbuf),0,1);
3222 SSVAL(smb_buf(outbuf),1,0);
3224 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3225 start_index, max_count));
3228 print_queue_struct *queue = NULL;
3229 print_status_struct status;
3230 char *p = smb_buf(outbuf) + 3;
3231 int count = print_queue_status(SNUM(conn), &queue, &status);
3232 int num_to_get = ABS(max_count);
3233 int first = (max_count>0?start_index:start_index+max_count+1);
3239 num_to_get = MIN(num_to_get,count-first);
3242 for (i=first;i<first+num_to_get;i++) {
3243 put_dos_date2(p,0,queue[i].time);
3244 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3245 SSVAL(p,5, queue[i].job);
3246 SIVAL(p,7,queue[i].size);
3248 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3253 outsize = set_message(outbuf,2,28*count+3,False);
3254 SSVAL(outbuf,smb_vwv0,count);
3255 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3256 SCVAL(smb_buf(outbuf),0,1);
3257 SSVAL(smb_buf(outbuf),1,28*count);
3262 DEBUG(3,("%d entries returned in queue\n",count));
3265 END_PROFILE(SMBsplretq);
3269 /****************************************************************************
3270 Reply to a printwrite.
3271 ****************************************************************************/
3273 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3276 int outsize = set_message(outbuf,0,0,True);
3278 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3280 START_PROFILE(SMBsplwr);
3282 if (!CAN_PRINT(conn)) {
3283 END_PROFILE(SMBsplwr);
3284 return ERROR_DOS(ERRDOS,ERRnoaccess);
3287 CHECK_FSP(fsp,conn);
3290 numtowrite = SVAL(smb_buf(inbuf),1);
3291 data = smb_buf(inbuf) + 3;
3293 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3294 END_PROFILE(SMBsplwr);
3295 return(UNIXERROR(ERRHRD,ERRdiskfull));
3298 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3300 END_PROFILE(SMBsplwr);
3304 /****************************************************************************
3305 The guts of the mkdir command, split out so it may be called by the NT SMB
3307 ****************************************************************************/
3309 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3311 BOOL bad_path = False;
3312 SMB_STRUCT_STAT sbuf;
3315 unix_convert(directory,conn,0,&bad_path,&sbuf);
3317 if( strchr_m(directory, ':')) {
3318 return NT_STATUS_NOT_A_DIRECTORY;
3321 if (ms_has_wild(directory)) {
3322 return NT_STATUS_OBJECT_NAME_INVALID;
3326 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3329 if (check_name(directory, conn))
3330 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3333 if(errno == ENOENT) {
3334 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3336 return map_nt_error_from_unix(errno);
3339 return NT_STATUS_OK;
3342 /****************************************************************************
3344 ****************************************************************************/
3346 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3351 START_PROFILE(SMBmkdir);
3353 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3354 if (!NT_STATUS_IS_OK(status)) {
3355 END_PROFILE(SMBmkdir);
3356 return ERROR_NT(status);
3359 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3361 status = mkdir_internal(conn, directory);
3362 if (!NT_STATUS_IS_OK(status)) {
3363 END_PROFILE(SMBmkdir);
3364 return ERROR_NT(status);
3367 outsize = set_message(outbuf,0,0,True);
3369 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3371 END_PROFILE(SMBmkdir);
3375 /****************************************************************************
3376 Static function used by reply_rmdir to delete an entire directory
3377 tree recursively. Return False on ok, True on fail.
3378 ****************************************************************************/
3380 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3382 const char *dname = NULL;
3385 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3390 while((dname = ReadDirName(dir_hnd, &offset))) {
3394 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3397 if (!is_visible_file(conn, directory, dname, &st, False))
3400 /* Construct the full name. */
3401 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3407 pstrcpy(fullname, directory);
3408 pstrcat(fullname, "/");
3409 pstrcat(fullname, dname);
3411 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3416 if(st.st_mode & S_IFDIR) {
3417 if(recursive_rmdir(conn, fullname)!=0) {
3421 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3425 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3434 /****************************************************************************
3435 The internals of the rmdir code - called elsewhere.
3436 ****************************************************************************/
3438 BOOL rmdir_internals(connection_struct *conn, char *directory)
3443 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3444 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3446 * Check to see if the only thing in this directory are
3447 * vetoed files/directories. If so then delete them and
3448 * retry. If we fail to delete any of them (and we *don't*
3449 * do a recursive delete) then fail the rmdir.
3451 BOOL all_veto_files = True;
3453 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3455 if(dir_hnd != NULL) {
3456 long dirpos = TellDir(dir_hnd);
3457 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3458 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3460 if (!is_visible_file(conn, directory, dname, &st, False))
3462 if(!IS_VETO_PATH(conn, dname)) {
3463 all_veto_files = False;
3468 if(all_veto_files) {
3469 SeekDir(dir_hnd,dirpos);
3470 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3473 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3475 if (!is_visible_file(conn, directory, dname, &st, False))
3478 /* Construct the full name. */
3479 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3484 pstrcpy(fullname, directory);
3485 pstrcat(fullname, "/");
3486 pstrcat(fullname, dname);
3488 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3490 if(st.st_mode & S_IFDIR) {
3491 if(lp_recursive_veto_delete(SNUM(conn))) {
3492 if(recursive_rmdir(conn, fullname) != 0)
3495 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3497 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3501 /* Retry the rmdir */
3502 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3512 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3517 /****************************************************************************
3519 ****************************************************************************/
3521 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3526 BOOL bad_path = False;
3527 SMB_STRUCT_STAT sbuf;
3529 START_PROFILE(SMBrmdir);
3531 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3532 if (!NT_STATUS_IS_OK(status)) {
3533 END_PROFILE(SMBrmdir);
3534 return ERROR_NT(status);
3537 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3539 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3541 END_PROFILE(SMBrmdir);
3542 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3545 if (check_name(directory,conn)) {
3546 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3547 ok = rmdir_internals(conn, directory);
3551 END_PROFILE(SMBrmdir);
3552 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3555 outsize = set_message(outbuf,0,0,True);
3557 DEBUG( 3, ( "rmdir %s\n", directory ) );
3559 END_PROFILE(SMBrmdir);
3563 /*******************************************************************
3564 Resolve wildcards in a filename rename.
3565 Note that name is in UNIX charset and thus potentially can be more
3566 than fstring buffer (255 bytes) especially in default UTF-8 case.
3567 Therefore, we use pstring inside and all calls should ensure that
3568 name2 is at least pstring-long (they do already)
3569 ********************************************************************/
3571 static BOOL resolve_wildcards(const char *name1, char *name2)
3573 pstring root1,root2;
3575 char *p,*p2, *pname1, *pname2;
3576 int available_space, actual_space;
3579 pname1 = strrchr_m(name1,'/');
3580 pname2 = strrchr_m(name2,'/');
3582 if (!pname1 || !pname2)
3585 pstrcpy(root1,pname1);
3586 pstrcpy(root2,pname2);
3587 p = strrchr_m(root1,'.');
3594 p = strrchr_m(root2,'.');
3608 } else if (*p2 == '*') {
3624 } else if (*p2 == '*') {
3634 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3637 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3638 if (actual_space >= available_space - 1) {
3639 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3640 actual_space - available_space));
3643 pstrcpy_base(pname2, root2, name2);
3649 /****************************************************************************
3650 Ensure open files have their names updates.
3651 ****************************************************************************/
3653 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3656 BOOL did_rename = False;
3658 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3659 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3660 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3661 fsp->fsp_name, newname ));
3662 string_set(&fsp->fsp_name, newname);
3667 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3668 (unsigned int)dev, (double)inode, newname ));
3671 /****************************************************************************
3672 Rename an open file - given an fsp.
3673 ****************************************************************************/
3675 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3677 SMB_STRUCT_STAT sbuf;
3678 BOOL bad_path = False;
3679 pstring newname_last_component;
3680 NTSTATUS error = NT_STATUS_OK;
3685 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3687 /* Quick check for "." and ".." */
3688 if (!bad_path && newname_last_component[0] == '.') {
3689 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3690 return NT_STATUS_ACCESS_DENIED;
3693 if (!rcdest && bad_path) {
3694 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3697 /* Ensure newname contains a '/' */
3698 if(strrchr_m(newname,'/') == 0) {
3701 pstrcpy(tmpstr, "./");
3702 pstrcat(tmpstr, newname);
3703 pstrcpy(newname, tmpstr);
3707 * Check for special case with case preserving and not
3708 * case sensitive. If the old last component differs from the original
3709 * last component only by case, then we should allow
3710 * the rename (user is trying to change the case of the
3714 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3715 strequal(newname, fsp->fsp_name)) {
3717 pstring newname_modified_last_component;
3720 * Get the last component of the modified name.
3721 * Note that we guarantee that newname contains a '/'
3724 p = strrchr_m(newname,'/');
3725 pstrcpy(newname_modified_last_component,p+1);
3727 if(strcsequal(newname_modified_last_component,
3728 newname_last_component) == False) {
3730 * Replace the modified last component with
3733 pstrcpy(p+1, newname_last_component);
3738 * If the src and dest names are identical - including case,
3739 * don't do the rename, just return success.
3742 if (strcsequal(fsp->fsp_name, newname)) {
3743 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3745 return NT_STATUS_OK;
3748 dest_exists = vfs_object_exist(conn,newname,NULL);
3750 if(!replace_if_exists && dest_exists) {
3751 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3752 fsp->fsp_name,newname));
3753 return NT_STATUS_OBJECT_NAME_COLLISION;
3756 error = can_rename(conn,newname,attrs,&sbuf);
3758 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3759 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3760 nt_errstr(error), fsp->fsp_name,newname));
3761 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3762 error = NT_STATUS_ACCESS_DENIED;
3766 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3767 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3768 fsp->fsp_name,newname));
3769 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3770 return NT_STATUS_OK;
3773 if (errno == ENOTDIR || errno == EISDIR)
3774 error = NT_STATUS_OBJECT_NAME_COLLISION;
3776 error = map_nt_error_from_unix(errno);
3778 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3779 nt_errstr(error), fsp->fsp_name,newname));
3784 /****************************************************************************
3785 The guts of the rename command, split out so it may be called by the NT SMB
3787 ****************************************************************************/
3789 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3793 pstring last_component_src;
3794 pstring last_component_dest;
3797 BOOL bad_path_src = False;
3798 BOOL bad_path_dest = False;
3800 NTSTATUS error = NT_STATUS_OK;
3803 SMB_STRUCT_STAT sbuf1, sbuf2;
3805 *directory = *mask = 0;
3810 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3811 if (!rc && bad_path_src) {
3812 if (ms_has_wild(last_component_src))
3813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3814 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3817 /* Quick check for "." and ".." */
3818 if (last_component_src[0] == '.') {
3819 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3820 return NT_STATUS_OBJECT_NAME_INVALID;
3824 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3826 /* Quick check for "." and ".." */
3827 if (last_component_dest[0] == '.') {
3828 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3829 return NT_STATUS_OBJECT_NAME_INVALID;
3834 * Split the old name into directory and last component
3835 * strings. Note that unix_convert may have stripped off a
3836 * leading ./ from both name and newname if the rename is
3837 * at the root of the share. We need to make sure either both
3838 * name and newname contain a / character or neither of them do
3839 * as this is checked in resolve_wildcards().
3842 p = strrchr_m(name,'/');
3844 pstrcpy(directory,".");
3848 pstrcpy(directory,name);
3850 *p = '/'; /* Replace needed for exceptional test below. */
3854 * We should only check the mangled cache
3855 * here if unix_convert failed. This means
3856 * that the path in 'mask' doesn't exist
3857 * on the file system and so we need to look
3858 * for a possible mangle. This patch from
3859 * Tine Smukavec <valentin.smukavec@hermes.si>.
3862 if (!rc && mangle_is_mangled(mask))
3863 mangle_check_cache( mask, sizeof(pstring)-1 );
3865 has_wild = ms_has_wild(mask);
3869 * No wildcards - just process the one file.
3871 BOOL is_short_name = mangle_is_8_3(name, True);
3873 /* Add a terminating '/' to the directory name. */
3874 pstrcat(directory,"/");
3875 pstrcat(directory,mask);
3877 /* Ensure newname contains a '/' also */
3878 if(strrchr_m(newname,'/') == 0) {
3881 pstrcpy(tmpstr, "./");
3882 pstrcat(tmpstr, newname);
3883 pstrcpy(newname, tmpstr);
3886 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3887 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3888 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3889 newname, last_component_dest, is_short_name));
3892 * Check for special case with case preserving and not
3893 * case sensitive, if directory and newname are identical,
3894 * and the old last component differs from the original
3895 * last component only by case, then we should allow
3896 * the rename (user is trying to change the case of the
3899 if((conn->case_sensitive == False) &&
3900 (((conn->case_preserve == True) &&
3901 (is_short_name == False)) ||
3902 ((conn->short_case_preserve == True) &&
3903 (is_short_name == True))) &&
3904 strcsequal(directory, newname)) {
3905 pstring modified_last_component;
3908 * Get the last component of the modified name.
3909 * Note that we guarantee that newname contains a '/'
3912 p = strrchr_m(newname,'/');
3913 pstrcpy(modified_last_component,p+1);
3915 if(strcsequal(modified_last_component,
3916 last_component_dest) == False) {
3918 * Replace the modified last component with
3921 pstrcpy(p+1, last_component_dest);
3925 resolve_wildcards(directory,newname);
3928 * The source object must exist.
3931 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3932 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3933 directory,newname));
3935 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3937 * Must return different errors depending on whether the parent
3938 * directory existed or not.
3941 p = strrchr_m(directory, '/');
3943 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3945 if (vfs_object_exist(conn, directory, NULL))
3946 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3947 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3949 error = map_nt_error_from_unix(errno);
3950 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3951 nt_errstr(error), directory,newname));
3956 if (!rcdest && bad_path_dest) {
3957 if (ms_has_wild(last_component_dest))
3958 return NT_STATUS_OBJECT_NAME_INVALID;
3959 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3962 error = can_rename(conn,directory,attrs,&sbuf1);
3964 if (!NT_STATUS_IS_OK(error)) {
3965 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3966 nt_errstr(error), directory,newname));
3971 * If the src and dest names are identical - including case,
3972 * don't do the rename, just return success.
3975 if (strcsequal(directory, newname)) {
3976 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3977 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3978 return NT_STATUS_OK;
3981 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3982 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3983 directory,newname));
3984 return NT_STATUS_OBJECT_NAME_COLLISION;
3987 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3988 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3989 directory,newname));
3990 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3991 return NT_STATUS_OK;
3994 if (errno == ENOTDIR || errno == EISDIR)
3995 error = NT_STATUS_OBJECT_NAME_COLLISION;
3997 error = map_nt_error_from_unix(errno);
3999 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4000 nt_errstr(error), directory,newname));
4005 * Wildcards - process each file that matches.
4007 struct smb_Dir *dir_hnd = NULL;
4011 if (check_name(directory,conn))
4012 dir_hnd = OpenDir(conn, directory);
4016 error = NT_STATUS_NO_SUCH_FILE;
4017 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4019 if (strequal(mask,"????????.???"))
4022 while ((dname = ReadDirName(dir_hnd, &offset))) {
4024 BOOL sysdir_entry = False;
4026 pstrcpy(fname,dname);
4028 /* Quick check for "." and ".." */
4029 if (fname[0] == '.') {
4030 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4032 sysdir_entry = True;
4039 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4042 if(!mask_match(fname, mask, conn->case_sensitive))
4046 error = NT_STATUS_OBJECT_NAME_INVALID;
4050 error = NT_STATUS_ACCESS_DENIED;
4051 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4052 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4053 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4054 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4057 error = can_rename(conn,fname,attrs,&sbuf1);
4058 if (!NT_STATUS_IS_OK(error)) {
4059 DEBUG(6,("rename %s refused\n", fname));
4062 pstrcpy(destname,newname);
4064 if (!resolve_wildcards(fname,destname)) {
4065 DEBUG(6,("resolve_wildcards %s %s failed\n",
4070 if (strcsequal(fname,destname)) {
4071 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4072 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4074 error = NT_STATUS_OK;
4078 if (!replace_if_exists &&
4079 vfs_file_exist(conn,destname, NULL)) {
4080 DEBUG(6,("file_exist %s\n", destname));
4081 error = NT_STATUS_OBJECT_NAME_COLLISION;
4085 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4086 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4088 error = NT_STATUS_OK;
4090 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4095 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4096 if (!rcdest && bad_path_dest) {
4097 if (ms_has_wild(last_component_dest))
4098 return NT_STATUS_OBJECT_NAME_INVALID;
4099 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4104 if (count == 0 && NT_STATUS_IS_OK(error)) {
4105 error = map_nt_error_from_unix(errno);
4111 /****************************************************************************
4113 ****************************************************************************/
4115 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4122 uint16 attrs = SVAL(inbuf,smb_vwv0);
4125 START_PROFILE(SMBmv);
4127 p = smb_buf(inbuf) + 1;
4128 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4129 if (!NT_STATUS_IS_OK(status)) {
4131 return ERROR_NT(status);
4134 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4135 if (!NT_STATUS_IS_OK(status)) {
4137 return ERROR_NT(status);
4140 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4141 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4143 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4145 status = rename_internals(conn, name, newname, attrs, False);
4146 if (!NT_STATUS_IS_OK(status)) {
4148 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4149 /* We have re-scheduled this call. */
4150 clear_cached_errors();
4153 return ERROR_NT(status);
4157 * Win2k needs a changenotify request response before it will
4158 * update after a rename..
4160 process_pending_change_notify_queue((time_t)0);
4161 outsize = set_message(outbuf,0,0,True);
4167 /*******************************************************************
4168 Copy a file as part of a reply_copy.
4169 ******************************************************************/
4171 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4172 int count,BOOL target_is_directory, int *err_ret)
4175 SMB_STRUCT_STAT src_sbuf, sbuf2;
4177 files_struct *fsp1,*fsp2;
4183 pstrcpy(dest,dest1);
4184 if (target_is_directory) {
4185 char *p = strrchr_m(src,'/');
4194 if (!vfs_file_exist(conn,src,&src_sbuf))
4197 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4198 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4204 if (!target_is_directory && count)
4205 ofun = FILE_EXISTS_OPEN;
4207 dosattrs = dos_mode(conn, src, &src_sbuf);
4208 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4209 ZERO_STRUCTP(&sbuf2);
4211 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4212 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4215 close_file(fsp1,False);
4219 if ((ofun&3) == 1) {
4220 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4221 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4223 * Stop the copy from occurring.
4226 src_sbuf.st_size = 0;
4230 if (src_sbuf.st_size)
4231 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4233 close_file(fsp1,False);
4235 /* Ensure the modtime is set correctly on the destination file. */
4236 fsp2->pending_modtime = src_sbuf.st_mtime;
4239 * As we are opening fsp1 read-only we only expect
4240 * an error on close on fsp2 if we are out of space.
4241 * Thus we don't look at the error return from the
4244 *err_ret = close_file(fsp2,False);
4246 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4249 /****************************************************************************
4250 Reply to a file copy.
4251 ****************************************************************************/
4253 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4258 pstring mask,newname;
4261 int error = ERRnoaccess;
4265 int tid2 = SVAL(inbuf,smb_vwv0);
4266 int ofun = SVAL(inbuf,smb_vwv1);
4267 int flags = SVAL(inbuf,smb_vwv2);
4268 BOOL target_is_directory=False;
4269 BOOL bad_path1 = False;
4270 BOOL bad_path2 = False;
4272 SMB_STRUCT_STAT sbuf1, sbuf2;
4275 START_PROFILE(SMBcopy);
4277 *directory = *mask = 0;
4280 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4281 if (!NT_STATUS_IS_OK(status)) {
4282 END_PROFILE(SMBcopy);
4283 return ERROR_NT(status);
4285 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4286 if (!NT_STATUS_IS_OK(status)) {
4287 END_PROFILE(SMBcopy);
4288 return ERROR_NT(status);
4291 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4293 if (tid2 != conn->cnum) {
4294 /* can't currently handle inter share copies XXXX */
4295 DEBUG(3,("Rejecting inter-share copy\n"));
4296 END_PROFILE(SMBcopy);
4297 return ERROR_DOS(ERRSRV,ERRinvdevice);
4300 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4301 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4303 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4304 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4306 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4308 if ((flags&1) && target_is_directory) {
4309 END_PROFILE(SMBcopy);
4310 return ERROR_DOS(ERRDOS,ERRbadfile);
4313 if ((flags&2) && !target_is_directory) {
4314 END_PROFILE(SMBcopy);
4315 return ERROR_DOS(ERRDOS,ERRbadpath);
4318 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4319 /* wants a tree copy! XXXX */
4320 DEBUG(3,("Rejecting tree copy\n"));
4321 END_PROFILE(SMBcopy);
4322 return ERROR_DOS(ERRSRV,ERRerror);
4325 p = strrchr_m(name,'/');
4327 pstrcpy(directory,"./");
4331 pstrcpy(directory,name);
4336 * We should only check the mangled cache
4337 * here if unix_convert failed. This means
4338 * that the path in 'mask' doesn't exist
4339 * on the file system and so we need to look
4340 * for a possible mangle. This patch from
4341 * Tine Smukavec <valentin.smukavec@hermes.si>.
4344 if (!rc && mangle_is_mangled(mask))
4345 mangle_check_cache( mask, sizeof(pstring)-1 );
4347 has_wild = ms_has_wild(mask);
4350 pstrcat(directory,"/");
4351 pstrcat(directory,mask);
4352 if (resolve_wildcards(directory,newname) &&
4353 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4357 END_PROFILE(SMBcopy);
4358 return(UNIXERROR(ERRHRD,ERRgeneral));
4361 exists = vfs_file_exist(conn,directory,NULL);
4364 struct smb_Dir *dir_hnd = NULL;
4368 if (check_name(directory,conn))
4369 dir_hnd = OpenDir(conn, directory);
4375 if (strequal(mask,"????????.???"))
4378 while ((dname = ReadDirName(dir_hnd, &offset))) {
4380 pstrcpy(fname,dname);
4382 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4385 if(!mask_match(fname, mask, conn->case_sensitive))
4388 error = ERRnoaccess;
4389 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4390 pstrcpy(destname,newname);
4391 if (resolve_wildcards(fname,destname) &&
4392 copy_file(fname,destname,conn,ofun,
4393 count,target_is_directory,&err))
4395 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4403 /* Error on close... */
4405 END_PROFILE(SMBcopy);
4406 return(UNIXERROR(ERRHRD,ERRgeneral));
4410 END_PROFILE(SMBcopy);
4411 return ERROR_DOS(ERRDOS,error);
4413 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4414 unix_ERR_class = ERRDOS;
4415 unix_ERR_code = ERRbadpath;
4417 END_PROFILE(SMBcopy);
4418 return(UNIXERROR(ERRDOS,error));
4422 outsize = set_message(outbuf,1,0,True);
4423 SSVAL(outbuf,smb_vwv0,count);
4425 END_PROFILE(SMBcopy);
4429 /****************************************************************************
4431 ****************************************************************************/
4433 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4441 START_PROFILE(pathworks_setdir);
4444 if (!CAN_SETDIR(snum)) {
4445 END_PROFILE(pathworks_setdir);
4446 return ERROR_DOS(ERRDOS,ERRnoaccess);
4449 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 END_PROFILE(pathworks_setdir);
4452 return ERROR_NT(status);
4455 if (strlen(newdir) == 0) {
4458 ok = vfs_directory_exist(conn,newdir,NULL);
4460 string_set(&conn->connectpath,newdir);
4464 END_PROFILE(pathworks_setdir);
4465 return ERROR_DOS(ERRDOS,ERRbadpath);
4468 outsize = set_message(outbuf,0,0,True);
4469 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4471 DEBUG(3,("setdir %s\n", newdir));
4473 END_PROFILE(pathworks_setdir);
4477 /****************************************************************************
4478 Get a lock pid, dealing with large count requests.
4479 ****************************************************************************/
4481 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4483 if(!large_file_format)
4484 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4486 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4489 /****************************************************************************
4490 Get a lock count, dealing with large count requests.
4491 ****************************************************************************/
4493 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4495 SMB_BIG_UINT count = 0;
4497 if(!large_file_format) {
4498 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4501 #if defined(HAVE_LONGLONG)
4502 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4503 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4504 #else /* HAVE_LONGLONG */
4507 * NT4.x seems to be broken in that it sends large file (64 bit)
4508 * lockingX calls even if the CAP_LARGE_FILES was *not*
4509 * negotiated. For boxes without large unsigned ints truncate the
4510 * lock count by dropping the top 32 bits.
4513 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4514 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4515 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4516 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4517 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4520 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4521 #endif /* HAVE_LONGLONG */
4527 #if !defined(HAVE_LONGLONG)
4528 /****************************************************************************
4529 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4530 ****************************************************************************/
4532 static uint32 map_lock_offset(uint32 high, uint32 low)
4536 uint32 highcopy = high;
4539 * Try and find out how many significant bits there are in high.
4542 for(i = 0; highcopy; i++)
4546 * We use 31 bits not 32 here as POSIX
4547 * lock offsets may not be negative.
4550 mask = (~0) << (31 - i);
4553 return 0; /* Fail. */
4559 #endif /* !defined(HAVE_LONGLONG) */
4561 /****************************************************************************
4562 Get a lock offset, dealing with large offset requests.
4563 ****************************************************************************/
4565 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4567 SMB_BIG_UINT offset = 0;
4571 if(!large_file_format) {
4572 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4575 #if defined(HAVE_LONGLONG)
4576 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4577 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4578 #else /* HAVE_LONGLONG */
4581 * NT4.x seems to be broken in that it sends large file (64 bit)
4582 * lockingX calls even if the CAP_LARGE_FILES was *not*
4583 * negotiated. For boxes without large unsigned ints mangle the
4584 * lock offset by mapping the top 32 bits onto the lower 32.
4587 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4588 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4589 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4592 if((new_low = map_lock_offset(high, low)) == 0) {
4594 return (SMB_BIG_UINT)-1;
4597 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4598 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4599 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4600 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4603 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4604 #endif /* HAVE_LONGLONG */
4610 /****************************************************************************
4611 Reply to a lockingX request.
4612 ****************************************************************************/
4614 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4616 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4617 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4618 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4619 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4620 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4621 SMB_BIG_UINT count = 0, offset = 0;
4623 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4626 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4628 BOOL my_lock_ctx = False;
4631 START_PROFILE(SMBlockingX);
4633 CHECK_FSP(fsp,conn);
4635 data = smb_buf(inbuf);
4637 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4638 /* we don't support these - and CANCEL_LOCK makes w2k
4639 and XP reboot so I don't really want to be
4640 compatible! (tridge) */
4641 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4644 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4645 /* Need to make this like a cancel.... JRA. */
4646 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4649 /* Check if this is an oplock break on a file
4650 we have granted an oplock on.
4652 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4653 /* Client can insist on breaking to none. */
4654 BOOL break_to_none = (oplocklevel == 0);
4656 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4657 (unsigned int)oplocklevel, fsp->fnum ));
4660 * Make sure we have granted an exclusive or batch oplock on this file.
4663 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4664 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4665 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4667 /* if this is a pure oplock break request then don't send a reply */
4668 if (num_locks == 0 && num_ulocks == 0) {
4669 END_PROFILE(SMBlockingX);
4672 END_PROFILE(SMBlockingX);
4673 return ERROR_DOS(ERRDOS,ERRlock);
4677 if (remove_oplock(fsp, break_to_none) == False) {
4678 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4682 /* if this is a pure oplock break request then don't send a reply */
4683 if (num_locks == 0 && num_ulocks == 0) {
4684 /* Sanity check - ensure a pure oplock break is not a
4686 if(CVAL(inbuf,smb_vwv0) != 0xff)
4687 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4688 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4689 END_PROFILE(SMBlockingX);
4695 * We do this check *after* we have checked this is not a oplock break
4696 * response message. JRA.
4699 release_level_2_oplocks_on_change(fsp);
4701 /* Data now points at the beginning of the list
4702 of smb_unlkrng structs */
4703 for(i = 0; i < (int)num_ulocks; i++) {
4704 lock_pid = get_lock_pid( data, i, large_file_format);
4705 count = get_lock_count( data, i, large_file_format);
4706 offset = get_lock_offset( data, i, large_file_format, &err);
4709 * There is no error code marked "stupid client bug".... :-).
4712 END_PROFILE(SMBlockingX);
4713 return ERROR_DOS(ERRDOS,ERRnoaccess);
4716 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4717 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4719 status = do_unlock(fsp,conn,lock_pid,count,offset);
4720 if (NT_STATUS_V(status)) {
4721 END_PROFILE(SMBlockingX);
4722 return ERROR_NT(status);
4726 /* Setup the timeout in seconds. */
4728 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4730 /* Now do any requested locks */
4731 data += ((large_file_format ? 20 : 10)*num_ulocks);
4733 /* Data now points at the beginning of the list
4734 of smb_lkrng structs */
4736 for(i = 0; i < (int)num_locks; i++) {
4737 lock_pid = get_lock_pid( data, i, large_file_format);
4738 count = get_lock_count( data, i, large_file_format);
4739 offset = get_lock_offset( data, i, large_file_format, &err);
4742 * There is no error code marked "stupid client bug".... :-).
4745 END_PROFILE(SMBlockingX);
4746 return ERROR_DOS(ERRDOS,ERRnoaccess);
4749 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4750 (double)offset, (double)count, (unsigned int)lock_pid,
4751 fsp->fsp_name, (int)lock_timeout ));
4753 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4754 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4755 if (NT_STATUS_V(status)) {
4757 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4758 * Even if it's our own lock context, we need to wait here as
4759 * there may be an unlock on the way.
4760 * So I removed a "&& !my_lock_ctx" from the following
4761 * if statement. JRA.
4763 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4765 * A blocking lock was requested. Package up
4766 * this smb into a queued request and push it
4767 * onto the blocking lock queue.
4769 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4770 END_PROFILE(SMBlockingX);
4778 /* If any of the above locks failed, then we must unlock
4779 all of the previous locks (X/Open spec). */
4780 if (i != num_locks && num_locks != 0) {
4782 * Ensure we don't do a remove on the lock that just failed,
4783 * as under POSIX rules, if we have a lock already there, we
4784 * will delete it (and we shouldn't) .....
4786 for(i--; i >= 0; i--) {
4787 lock_pid = get_lock_pid( data, i, large_file_format);
4788 count = get_lock_count( data, i, large_file_format);
4789 offset = get_lock_offset( data, i, large_file_format, &err);
4792 * There is no error code marked "stupid client bug".... :-).
4795 END_PROFILE(SMBlockingX);
4796 return ERROR_DOS(ERRDOS,ERRnoaccess);
4799 do_unlock(fsp,conn,lock_pid,count,offset);
4801 END_PROFILE(SMBlockingX);
4802 return ERROR_NT(status);
4805 set_message(outbuf,2,0,True);
4807 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4808 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4810 END_PROFILE(SMBlockingX);
4811 return chain_reply(inbuf,outbuf,length,bufsize);
4814 /****************************************************************************
4815 Reply to a SMBreadbmpx (read block multiplex) request.
4816 ****************************************************************************/
4818 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4829 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4830 START_PROFILE(SMBreadBmpx);
4832 /* this function doesn't seem to work - disable by default */
4833 if (!lp_readbmpx()) {
4834 END_PROFILE(SMBreadBmpx);
4835 return ERROR_DOS(ERRSRV,ERRuseSTD);
4838 outsize = set_message(outbuf,8,0,True);
4840 CHECK_FSP(fsp,conn);
4843 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4844 maxcount = SVAL(inbuf,smb_vwv3);
4846 data = smb_buf(outbuf);
4847 pad = ((long)data)%4;
4852 max_per_packet = bufsize-(outsize+pad);
4856 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4857 END_PROFILE(SMBreadBmpx);
4858 return ERROR_DOS(ERRDOS,ERRlock);
4862 size_t N = MIN(max_per_packet,tcount-total_read);
4864 nread = read_file(fsp,data,startpos,N);
4869 if (nread < (ssize_t)N)
4870 tcount = total_read + nread;
4872 set_message(outbuf,8,nread,False);
4873 SIVAL(outbuf,smb_vwv0,startpos);
4874 SSVAL(outbuf,smb_vwv2,tcount);
4875 SSVAL(outbuf,smb_vwv6,nread);
4876 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4878 if (!send_smb(smbd_server_fd(),outbuf))
4879 exit_server("reply_readbmpx: send_smb failed.");
4881 total_read += nread;
4883 } while (total_read < (ssize_t)tcount);
4885 END_PROFILE(SMBreadBmpx);
4889 /****************************************************************************
4890 Reply to a SMBsetattrE.
4891 ****************************************************************************/
4893 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4895 struct utimbuf unix_times;
4897 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4898 START_PROFILE(SMBsetattrE);
4900 outsize = set_message(outbuf,0,0,True);
4902 if(!fsp || (fsp->conn != conn)) {
4903 END_PROFILE(SMBgetattrE);
4904 return ERROR_DOS(ERRDOS,ERRbadfid);
4908 * Convert the DOS times into unix times. Ignore create
4909 * time as UNIX can't set this.
4912 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4913 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4916 * Patch from Ray Frush <frush@engr.colostate.edu>
4917 * Sometimes times are sent as zero - ignore them.
4920 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4921 /* Ignore request */
4922 if( DEBUGLVL( 3 ) ) {
4923 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4924 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4926 END_PROFILE(SMBsetattrE);
4928 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4929 /* set modify time = to access time if modify time was 0 */
4930 unix_times.modtime = unix_times.actime;
4933 /* Set the date on this file */
4934 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4935 END_PROFILE(SMBsetattrE);
4936 return ERROR_DOS(ERRDOS,ERRnoaccess);
4939 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4940 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4942 END_PROFILE(SMBsetattrE);
4947 /* Back from the dead for OS/2..... JRA. */
4949 /****************************************************************************
4950 Reply to a SMBwritebmpx (write block multiplex primary) request.
4951 ****************************************************************************/
4953 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4956 ssize_t nwritten = -1;
4963 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4964 START_PROFILE(SMBwriteBmpx);
4966 CHECK_FSP(fsp,conn);
4970 tcount = SVAL(inbuf,smb_vwv1);
4971 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4972 write_through = BITSETW(inbuf+smb_vwv7,0);
4973 numtowrite = SVAL(inbuf,smb_vwv10);
4974 smb_doff = SVAL(inbuf,smb_vwv11);
4976 data = smb_base(inbuf) + smb_doff;
4978 /* If this fails we need to send an SMBwriteC response,
4979 not an SMBwritebmpx - set this up now so we don't forget */
4980 SCVAL(outbuf,smb_com,SMBwritec);
4982 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4983 END_PROFILE(SMBwriteBmpx);
4984 return(ERROR_DOS(ERRDOS,ERRlock));
4987 nwritten = write_file(fsp,data,startpos,numtowrite);
4989 if(lp_syncalways(SNUM(conn)) || write_through)
4990 sync_file(conn,fsp);
4992 if(nwritten < (ssize_t)numtowrite) {
4993 END_PROFILE(SMBwriteBmpx);
4994 return(UNIXERROR(ERRHRD,ERRdiskfull));
4997 /* If the maximum to be written to this file
4998 is greater than what we just wrote then set
4999 up a secondary struct to be attached to this
5000 fd, we will use this to cache error messages etc. */
5002 if((ssize_t)tcount > nwritten) {
5003 write_bmpx_struct *wbms;
5004 if(fsp->wbmpx_ptr != NULL)
5005 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5007 wbms = SMB_MALLOC_P(write_bmpx_struct);
5009 DEBUG(0,("Out of memory in reply_readmpx\n"));
5010 END_PROFILE(SMBwriteBmpx);
5011 return(ERROR_DOS(ERRSRV,ERRnoresource));
5013 wbms->wr_mode = write_through;
5014 wbms->wr_discard = False; /* No errors yet */
5015 wbms->wr_total_written = nwritten;
5016 wbms->wr_errclass = 0;
5018 fsp->wbmpx_ptr = wbms;
5021 /* We are returning successfully, set the message type back to
5023 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5025 outsize = set_message(outbuf,1,0,True);
5027 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5029 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5030 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5032 if (write_through && tcount==nwritten) {
5033 /* We need to send both a primary and a secondary response */
5034 smb_setlen(outbuf,outsize - 4);
5035 if (!send_smb(smbd_server_fd(),outbuf))
5036 exit_server("reply_writebmpx: send_smb failed.");
5038 /* Now the secondary */
5039 outsize = set_message(outbuf,1,0,True);
5040 SCVAL(outbuf,smb_com,SMBwritec);
5041 SSVAL(outbuf,smb_vwv0,nwritten);
5044 END_PROFILE(SMBwriteBmpx);
5048 /****************************************************************************
5049 Reply to a SMBwritebs (write block multiplex secondary) request.
5050 ****************************************************************************/
5052 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5055 ssize_t nwritten = -1;
5062 write_bmpx_struct *wbms;
5063 BOOL send_response = False;
5064 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5065 START_PROFILE(SMBwriteBs);
5067 CHECK_FSP(fsp,conn);
5070 tcount = SVAL(inbuf,smb_vwv1);
5071 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5072 numtowrite = SVAL(inbuf,smb_vwv6);
5073 smb_doff = SVAL(inbuf,smb_vwv7);
5075 data = smb_base(inbuf) + smb_doff;
5077 /* We need to send an SMBwriteC response, not an SMBwritebs */
5078 SCVAL(outbuf,smb_com,SMBwritec);
5080 /* This fd should have an auxiliary struct attached,
5081 check that it does */
5082 wbms = fsp->wbmpx_ptr;
5084 END_PROFILE(SMBwriteBs);
5088 /* If write through is set we can return errors, else we must cache them */
5089 write_through = wbms->wr_mode;
5091 /* Check for an earlier error */
5092 if(wbms->wr_discard) {
5093 END_PROFILE(SMBwriteBs);
5094 return -1; /* Just discard the packet */
5097 nwritten = write_file(fsp,data,startpos,numtowrite);
5099 if(lp_syncalways(SNUM(conn)) || write_through)
5100 sync_file(conn,fsp);
5102 if (nwritten < (ssize_t)numtowrite) {
5104 /* We are returning an error - we can delete the aux struct */
5107 fsp->wbmpx_ptr = NULL;
5108 END_PROFILE(SMBwriteBs);
5109 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5111 END_PROFILE(SMBwriteBs);
5112 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5115 /* Increment the total written, if this matches tcount
5116 we can discard the auxiliary struct (hurrah !) and return a writeC */
5117 wbms->wr_total_written += nwritten;
5118 if(wbms->wr_total_written >= tcount) {
5119 if (write_through) {
5120 outsize = set_message(outbuf,1,0,True);
5121 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5122 send_response = True;
5126 fsp->wbmpx_ptr = NULL;
5130 END_PROFILE(SMBwriteBs);
5134 END_PROFILE(SMBwriteBs);
5138 /****************************************************************************
5139 Reply to a SMBgetattrE.
5140 ****************************************************************************/
5142 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5144 SMB_STRUCT_STAT sbuf;
5147 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5148 START_PROFILE(SMBgetattrE);
5150 outsize = set_message(outbuf,11,0,True);
5152 if(!fsp || (fsp->conn != conn)) {
5153 END_PROFILE(SMBgetattrE);
5154 return ERROR_DOS(ERRDOS,ERRbadfid);
5157 /* Do an fstat on this file */
5158 if(fsp_stat(fsp, &sbuf)) {
5159 END_PROFILE(SMBgetattrE);
5160 return(UNIXERROR(ERRDOS,ERRnoaccess));
5163 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5166 * Convert the times into dos times. Set create
5167 * date to be last modify date as UNIX doesn't save
5171 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5172 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5173 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5176 SIVAL(outbuf,smb_vwv6,0);
5177 SIVAL(outbuf,smb_vwv8,0);
5179 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5180 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5181 SIVAL(outbuf,smb_vwv8,allocation_size);
5183 SSVAL(outbuf,smb_vwv10, mode);
5185 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5187 END_PROFILE(SMBgetattrE);