2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
33 extern char magic_char;
34 extern int global_oplock_break;
35 unsigned int smb_echo_count = 0;
36 extern uint32 global_client_caps;
38 extern BOOL global_encrypted_passwords_negotiated;
40 /****************************************************************************
41 Ensure we check the path in *exactly* the same way as W2K.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
50 const char *s = srcname;
51 NTSTATUS ret = NT_STATUS_OK;
52 BOOL start_of_name_component = True;
53 unsigned int num_bad_components = 0;
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
69 start_of_name_component = True;
73 if (start_of_name_component) {
74 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
75 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
78 * No mb char starts with '.' so we're safe checking the directory separator here.
81 /* If we just added a '/' - delete it */
82 if ((d > destname) && (*(d-1) == '/')) {
87 /* Are we at the start ? Can't go back further if so. */
89 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
92 /* Go back one level... */
93 /* We know this is safe as '/' cannot be part of a mb sequence. */
94 /* NOTE - if this assumption is invalid we are not in good shape... */
95 /* Decrement d first as d points to the *next* char to write into. */
96 for (d--; d > destname; d--) {
100 s += 2; /* Else go past the .. */
101 /* We're still at the start of a name component, just the previous one. */
103 if (num_bad_components) {
104 /* Hmmm. Should we only decrement the bad_components if
105 we're removing a bad component ? Need to check this. JRA. */
106 num_bad_components--;
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112 /* Component of pathname can't be "." only. */
113 ret = NT_STATUS_OBJECT_NAME_INVALID;
114 num_bad_components++;
121 if (allow_wcard_names) {
130 return NT_STATUS_OBJECT_NAME_INVALID;
137 switch(next_mb_char_size(s)) {
148 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
150 return NT_STATUS_INVALID_PARAMETER;
153 if (start_of_name_component && num_bad_components) {
154 num_bad_components++;
156 start_of_name_component = False;
159 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
160 /* For some strange reason being called from findfirst changes
161 the num_components number to cause the error return to change. JRA. */
162 if (allow_wcard_names) {
163 if (num_bad_components > 2) {
164 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
167 if (num_bad_components > 1) {
168 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
177 /****************************************************************************
178 Pull a string and check the path - provide for error return.
179 ****************************************************************************/
181 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
184 char *tmppath_ptr = tmppath;
187 SMB_ASSERT(dest_len == sizeof(pstring));
191 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
193 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
195 *err = check_path_syntax(dest, tmppath, allow_wcard_names);
199 /****************************************************************************
200 Reply to a special message.
201 ****************************************************************************/
203 int reply_special(char *inbuf,char *outbuf)
206 int msg_type = CVAL(inbuf,0);
207 int msg_flags = CVAL(inbuf,1);
211 static BOOL already_got_session = False;
215 memset(outbuf,'\0',smb_size);
217 smb_setlen(outbuf,0);
220 case 0x81: /* session request */
222 if (already_got_session) {
223 exit_server("multiple session request not permitted");
226 SCVAL(outbuf,0,0x82);
228 if (name_len(inbuf+4) > 50 ||
229 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
230 DEBUG(0,("Invalid name length in session request\n"));
233 name_extract(inbuf,4,name1);
234 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
235 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
238 set_local_machine_name(name1, True);
239 set_remote_machine_name(name2, True);
241 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
242 get_local_machine_name(), get_remote_machine_name(),
245 if (name_type == 'R') {
246 /* We are being asked for a pathworks session ---
248 SCVAL(outbuf, 0,0x83);
252 /* only add the client's machine name to the list
253 of possibly valid usernames if we are operating
254 in share mode security */
255 if (lp_security() == SEC_SHARE) {
256 add_session_user(get_remote_machine_name());
259 reload_services(True);
262 already_got_session = True;
265 case 0x89: /* session keepalive request
266 (some old clients produce this?) */
267 SCVAL(outbuf,0,SMBkeepalive);
271 case 0x82: /* positive session response */
272 case 0x83: /* negative session response */
273 case 0x84: /* retarget session response */
274 DEBUG(0,("Unexpected session response\n"));
277 case SMBkeepalive: /* session keepalive */
282 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
283 msg_type, msg_flags));
288 /****************************************************************************
290 ****************************************************************************/
292 int reply_tcon(connection_struct *conn,
293 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
300 uint16 vuid = SVAL(inbuf,smb_uid);
304 DATA_BLOB password_blob;
306 START_PROFILE(SMBtcon);
308 *service_buf = *password = *dev = 0;
310 p = smb_buf(inbuf)+1;
311 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
312 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
314 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
316 p = strrchr_m(service_buf,'\\');
320 service = service_buf;
323 password_blob = data_blob(password, pwlen+1);
325 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
327 data_blob_clear_free(&password_blob);
330 END_PROFILE(SMBtcon);
331 return ERROR_NT(nt_status);
334 outsize = set_message(outbuf,2,0,True);
335 SSVAL(outbuf,smb_vwv0,max_recv);
336 SSVAL(outbuf,smb_vwv1,conn->cnum);
337 SSVAL(outbuf,smb_tid,conn->cnum);
339 DEBUG(3,("tcon service=%s cnum=%d\n",
340 service, conn->cnum));
342 END_PROFILE(SMBtcon);
346 /****************************************************************************
347 Reply to a tcon and X.
348 ****************************************************************************/
350 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
355 /* what the cleint thinks the device is */
356 fstring client_devicetype;
357 /* what the server tells the client the share represents */
358 const char *server_devicetype;
360 uint16 vuid = SVAL(inbuf,smb_uid);
361 int passlen = SVAL(inbuf,smb_vwv3);
364 extern BOOL global_encrypted_passwords_negotiated;
366 START_PROFILE(SMBtconX);
368 *service = *client_devicetype = 0;
370 /* we might have to close an old one */
371 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
372 close_cnum(conn,vuid);
375 if (passlen > MAX_PASS_LEN) {
376 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
379 if (global_encrypted_passwords_negotiated) {
380 password = data_blob(smb_buf(inbuf),passlen);
382 password = data_blob(smb_buf(inbuf),passlen+1);
383 /* Ensure correct termination */
384 password.data[passlen]=0;
387 p = smb_buf(inbuf) + passlen;
388 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
391 * the service name can be either: \\server\share
392 * or share directly like on the DELL PowerVault 705
395 q = strchr_m(path+2,'\\');
397 END_PROFILE(SMBtconX);
398 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
400 fstrcpy(service,q+1);
403 fstrcpy(service,path);
405 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
407 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
409 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
411 data_blob_clear_free(&password);
414 END_PROFILE(SMBtconX);
415 return ERROR_NT(nt_status);
419 server_devicetype = "IPC";
420 else if ( IS_PRINT(conn) )
421 server_devicetype = "LPT1:";
423 server_devicetype = "A:";
425 if (Protocol < PROTOCOL_NT1) {
426 set_message(outbuf,2,0,True);
428 p += srvstr_push(outbuf, p, server_devicetype, -1,
429 STR_TERMINATE|STR_ASCII);
430 set_message_end(outbuf,p);
432 /* NT sets the fstype of IPC$ to the null string */
433 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
435 set_message(outbuf,3,0,True);
438 p += srvstr_push(outbuf, p, server_devicetype, -1,
439 STR_TERMINATE|STR_ASCII);
440 p += srvstr_push(outbuf, p, fstype, -1,
443 set_message_end(outbuf,p);
445 /* what does setting this bit do? It is set by NT4 and
446 may affect the ability to autorun mounted cdroms */
447 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
448 (lp_csc_policy(SNUM(conn)) << 2));
450 init_dfsroot(conn, inbuf, outbuf);
454 DEBUG(3,("tconX service=%s \n",
457 /* set the incoming and outgoing tid to the just created one */
458 SSVAL(inbuf,smb_tid,conn->cnum);
459 SSVAL(outbuf,smb_tid,conn->cnum);
461 END_PROFILE(SMBtconX);
462 return chain_reply(inbuf,outbuf,length,bufsize);
465 /****************************************************************************
466 Reply to an unknown type.
467 ****************************************************************************/
469 int reply_unknown(char *inbuf,char *outbuf)
472 type = CVAL(inbuf,smb_com);
474 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
475 smb_fn_name(type), type, type));
477 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
480 /****************************************************************************
482 ****************************************************************************/
484 int reply_ioctl(connection_struct *conn,
485 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
487 uint16 device = SVAL(inbuf,smb_vwv1);
488 uint16 function = SVAL(inbuf,smb_vwv2);
489 uint32 ioctl_code = (device << 16) + function;
490 int replysize, outsize;
492 START_PROFILE(SMBioctl);
494 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
496 switch (ioctl_code) {
497 case IOCTL_QUERY_JOB_INFO:
501 END_PROFILE(SMBioctl);
502 return(ERROR_DOS(ERRSRV,ERRnosupport));
505 outsize = set_message(outbuf,8,replysize+1,True);
506 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
507 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
508 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
509 p = smb_buf(outbuf) + 1; /* Allow for alignment */
511 switch (ioctl_code) {
512 case IOCTL_QUERY_JOB_INFO:
514 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
516 END_PROFILE(SMBioctl);
517 return(UNIXERROR(ERRDOS,ERRbadfid));
519 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
520 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
522 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
528 END_PROFILE(SMBioctl);
532 /****************************************************************************
534 ****************************************************************************/
536 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
541 BOOL bad_path = False;
542 SMB_STRUCT_STAT sbuf;
545 START_PROFILE(SMBchkpth);
547 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
548 if (!NT_STATUS_IS_OK(status)) {
549 END_PROFILE(SMBchkpth);
550 return ERROR_NT(status);
553 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
555 unix_convert(name,conn,0,&bad_path,&sbuf);
557 END_PROFILE(SMBchkpth);
558 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
561 if (check_name(name,conn)) {
562 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
563 if (!(ok = S_ISDIR(sbuf.st_mode))) {
564 END_PROFILE(SMBchkpth);
565 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
570 /* We special case this - as when a Windows machine
571 is parsing a path is steps through the components
572 one at a time - if a component fails it expects
573 ERRbadpath, not ERRbadfile.
575 if(errno == ENOENT) {
577 * Windows returns different error codes if
578 * the parent directory is valid but not the
579 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
580 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
581 * if the path is invalid. This is different from set_bad_path_error()
582 * in the non-NT error case.
584 END_PROFILE(SMBchkpth);
585 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
588 END_PROFILE(SMBchkpth);
589 return(UNIXERROR(ERRDOS,ERRbadpath));
592 outsize = set_message(outbuf,0,0,True);
593 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
595 END_PROFILE(SMBchkpth);
599 /****************************************************************************
601 ****************************************************************************/
603 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
607 SMB_STRUCT_STAT sbuf;
612 BOOL bad_path = False;
616 START_PROFILE(SMBgetatr);
618 p = smb_buf(inbuf) + 1;
619 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
620 if (!NT_STATUS_IS_OK(status)) {
621 END_PROFILE(SMBgetatr);
622 return ERROR_NT(status);
625 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
627 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
628 under WfWg - weird! */
630 mode = aHIDDEN | aDIR;
631 if (!CAN_WRITE(conn))
637 unix_convert(fname,conn,0,&bad_path,&sbuf);
639 END_PROFILE(SMBgetatr);
640 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
642 if (check_name(fname,conn)) {
643 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
644 mode = dos_mode(conn,fname,&sbuf);
646 mtime = sbuf.st_mtime;
651 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
657 END_PROFILE(SMBgetatr);
658 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
661 outsize = set_message(outbuf,10,0,True);
663 SSVAL(outbuf,smb_vwv0,mode);
664 if(lp_dos_filetime_resolution(SNUM(conn)) )
665 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
667 put_dos_date3(outbuf,smb_vwv1,mtime);
668 SIVAL(outbuf,smb_vwv3,(uint32)size);
670 if (Protocol >= PROTOCOL_NT1)
671 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
673 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
675 END_PROFILE(SMBgetatr);
679 /****************************************************************************
681 ****************************************************************************/
683 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
690 SMB_STRUCT_STAT sbuf;
691 BOOL bad_path = False;
695 START_PROFILE(SMBsetatr);
697 p = smb_buf(inbuf) + 1;
698 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
699 if (!NT_STATUS_IS_OK(status)) {
700 END_PROFILE(SMBsetatr);
701 return ERROR_NT(status);
704 unix_convert(fname,conn,0,&bad_path,&sbuf);
706 END_PROFILE(SMBsetatr);
707 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
710 mode = SVAL(inbuf,smb_vwv0);
711 mtime = make_unix_date3(inbuf+smb_vwv1);
713 if (mode != FILE_ATTRIBUTE_NORMAL) {
714 if (VALID_STAT_OF_DIR(sbuf))
719 if (check_name(fname,conn)) {
720 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
727 ok = set_filetime(conn,fname,mtime);
730 END_PROFILE(SMBsetatr);
731 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
734 outsize = set_message(outbuf,0,0,True);
736 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
738 END_PROFILE(SMBsetatr);
742 /****************************************************************************
744 ****************************************************************************/
746 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
749 SMB_BIG_UINT dfree,dsize,bsize;
750 START_PROFILE(SMBdskattr);
752 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
754 outsize = set_message(outbuf,5,0,True);
756 if (Protocol <= PROTOCOL_LANMAN2) {
757 double total_space, free_space;
758 /* we need to scale this to a number that DOS6 can handle. We
759 use floating point so we can handle large drives on systems
760 that don't have 64 bit integers
762 we end up displaying a maximum of 2G to DOS systems
764 total_space = dsize * (double)bsize;
765 free_space = dfree * (double)bsize;
767 dsize = (total_space+63*512) / (64*512);
768 dfree = (free_space+63*512) / (64*512);
770 if (dsize > 0xFFFF) dsize = 0xFFFF;
771 if (dfree > 0xFFFF) dfree = 0xFFFF;
773 SSVAL(outbuf,smb_vwv0,dsize);
774 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
775 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
776 SSVAL(outbuf,smb_vwv3,dfree);
778 SSVAL(outbuf,smb_vwv0,dsize);
779 SSVAL(outbuf,smb_vwv1,bsize/512);
780 SSVAL(outbuf,smb_vwv2,512);
781 SSVAL(outbuf,smb_vwv3,dfree);
784 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
786 END_PROFILE(SMBdskattr);
790 /****************************************************************************
792 Can be called from SMBsearch, SMBffirst or SMBfunique.
793 ****************************************************************************/
795 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
805 unsigned int numentries = 0;
806 unsigned int maxentries = 0;
807 BOOL finished = False;
814 BOOL check_descend = False;
815 BOOL expect_close = False;
816 BOOL can_open = True;
817 BOOL bad_path = False;
819 START_PROFILE(SMBsearch);
821 *mask = *directory = *fname = 0;
823 /* If we were called as SMBffirst then we must expect close. */
824 if(CVAL(inbuf,smb_com) == SMBffirst)
827 outsize = set_message(outbuf,1,3,True);
828 maxentries = SVAL(inbuf,smb_vwv0);
829 dirtype = SVAL(inbuf,smb_vwv1);
830 p = smb_buf(inbuf) + 1;
831 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
832 if (!NT_STATUS_IS_OK(nt_status)) {
833 END_PROFILE(SMBsearch);
834 return ERROR_NT(nt_status);
837 status_len = SVAL(p, 0);
840 /* dirtype &= ~aDIR; */
842 if (status_len == 0) {
843 SMB_STRUCT_STAT sbuf;
846 pstrcpy(directory,path);
848 unix_convert(directory,conn,0,&bad_path,&sbuf);
851 if (!check_name(directory,conn))
854 p = strrchr_m(dir2,'/');
863 p = strrchr_m(directory,'/');
869 if (strlen(directory) == 0)
870 pstrcpy(directory,".");
871 memset((char *)status,'\0',21);
872 SCVAL(status,0,(dirtype & 0x1F));
877 status_dirtype = CVAL(status,0) & 0x1F;
878 if (status_dirtype != (dirtype & 0x1F))
879 dirtype = status_dirtype;
881 conn->dirptr = dptr_fetch(status+12,&dptr_num);
884 string_set(&conn->dirpath,dptr_path(dptr_num));
885 pstrcpy(mask, dptr_wcard(dptr_num));
889 p = smb_buf(outbuf) + 3;
892 if (status_len == 0) {
893 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
896 END_PROFILE(SMBsearch);
897 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
899 END_PROFILE(SMBsearch);
900 return ERROR_DOS(ERRDOS,ERRnofids);
902 dptr_set_wcard(dptr_num, SMB_STRDUP(mask));
903 dptr_set_attr(dptr_num, dirtype);
905 dirtype = dptr_attr(dptr_num);
908 DEBUG(4,("dptr_num is %d\n",dptr_num));
911 if ((dirtype&0x1F) == aVOLID) {
913 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
914 dptr_fill(p+12,dptr_num);
915 if (dptr_zero(p+12) && (status_len==0))
919 p += DIR_STRUCT_SIZE;
922 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
924 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
925 conn->dirpath,lp_dontdescend(SNUM(conn))));
926 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
927 check_descend = True;
929 for (i=numentries;(i<maxentries) && !finished;i++) {
930 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
933 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
934 dptr_fill(p+12,dptr_num);
936 p += DIR_STRUCT_SIZE;
946 /* If we were called as SMBffirst with smb_search_id == NULL
947 and no entries were found then return error and close dirptr
950 if(ok && expect_close && numentries == 0 && status_len == 0) {
951 /* Close the dptr - we know it's gone */
952 dptr_close(&dptr_num);
953 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
954 } else if (numentries == 0 || !ok) {
955 dptr_close(&dptr_num);
956 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
959 /* If we were called as SMBfunique, then we can close the dirptr now ! */
960 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
961 dptr_close(&dptr_num);
963 SSVAL(outbuf,smb_vwv0,numentries);
964 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
965 SCVAL(smb_buf(outbuf),0,5);
966 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
968 if (Protocol >= PROTOCOL_NT1)
969 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
971 outsize += DIR_STRUCT_SIZE*numentries;
972 smb_setlen(outbuf,outsize - 4);
974 if ((! *directory) && dptr_path(dptr_num))
975 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
977 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
978 smb_fn_name(CVAL(inbuf,smb_com)),
979 mask, directory, dirtype, numentries, maxentries ) );
981 END_PROFILE(SMBsearch);
985 /****************************************************************************
986 Reply to a fclose (stop directory search).
987 ****************************************************************************/
989 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
999 START_PROFILE(SMBfclose);
1001 outsize = set_message(outbuf,1,0,True);
1002 p = smb_buf(inbuf) + 1;
1003 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1004 if (!NT_STATUS_IS_OK(err)) {
1005 END_PROFILE(SMBfclose);
1006 return ERROR_NT(err);
1009 status_len = SVAL(p,0);
1012 if (status_len == 0) {
1013 END_PROFILE(SMBfclose);
1014 return ERROR_DOS(ERRSRV,ERRsrverror);
1017 memcpy(status,p,21);
1019 if(dptr_fetch(status+12,&dptr_num)) {
1020 /* Close the dptr - we know it's gone */
1021 dptr_close(&dptr_num);
1024 SSVAL(outbuf,smb_vwv0,0);
1026 DEBUG(3,("search close\n"));
1028 END_PROFILE(SMBfclose);
1032 /****************************************************************************
1034 ****************************************************************************/
1036 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1045 SMB_STRUCT_STAT sbuf;
1046 BOOL bad_path = False;
1048 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1049 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1051 START_PROFILE(SMBopen);
1053 share_mode = SVAL(inbuf,smb_vwv0);
1055 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1056 if (!NT_STATUS_IS_OK(status)) {
1057 END_PROFILE(SMBopen);
1058 return ERROR_NT(status);
1061 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1063 unix_convert(fname,conn,0,&bad_path,&sbuf);
1065 END_PROFILE(SMBopen);
1066 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1069 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1070 (uint32)dos_attr, oplock_request,&rmode,NULL);
1073 END_PROFILE(SMBopen);
1074 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1075 /* We have re-scheduled this call. */
1076 clear_cached_errors();
1079 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1082 size = sbuf.st_size;
1083 fmode = dos_mode(conn,fname,&sbuf);
1084 mtime = sbuf.st_mtime;
1087 DEBUG(3,("attempt to open a directory %s\n",fname));
1088 close_file(fsp,False);
1089 END_PROFILE(SMBopen);
1090 return ERROR_DOS(ERRDOS,ERRnoaccess);
1093 outsize = set_message(outbuf,7,0,True);
1094 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1095 SSVAL(outbuf,smb_vwv1,fmode);
1096 if(lp_dos_filetime_resolution(SNUM(conn)) )
1097 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1099 put_dos_date3(outbuf,smb_vwv2,mtime);
1100 SIVAL(outbuf,smb_vwv4,(uint32)size);
1101 SSVAL(outbuf,smb_vwv6,rmode);
1103 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1104 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1106 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1107 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1108 END_PROFILE(SMBopen);
1112 /****************************************************************************
1113 Reply to an open and X.
1114 ****************************************************************************/
1116 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1119 int smb_mode = SVAL(inbuf,smb_vwv3);
1120 int smb_attr = SVAL(inbuf,smb_vwv5);
1121 /* Breakout the oplock request bits so we can set the
1122 reply bits separately. */
1123 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1124 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1125 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1127 int open_flags = SVAL(inbuf,smb_vwv2);
1128 int smb_sattr = SVAL(inbuf,smb_vwv4);
1129 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1131 int smb_ofun = SVAL(inbuf,smb_vwv8);
1133 int fmode=0,mtime=0,rmode=0;
1134 SMB_STRUCT_STAT sbuf;
1136 BOOL bad_path = False;
1139 START_PROFILE(SMBopenX);
1141 /* If it's an IPC, pass off the pipe handler. */
1143 if (lp_nt_pipe_support()) {
1144 END_PROFILE(SMBopenX);
1145 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1147 END_PROFILE(SMBopenX);
1148 return ERROR_DOS(ERRSRV,ERRaccess);
1152 /* XXXX we need to handle passed times, sattr and flags */
1153 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1154 if (!NT_STATUS_IS_OK(status)) {
1155 END_PROFILE(SMBopenX);
1156 return ERROR_NT(status);
1159 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1161 unix_convert(fname,conn,0,&bad_path,&sbuf);
1163 END_PROFILE(SMBopenX);
1164 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1167 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1168 oplock_request, &rmode,&smb_action);
1171 END_PROFILE(SMBopenX);
1172 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1173 /* We have re-scheduled this call. */
1174 clear_cached_errors();
1177 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1180 size = sbuf.st_size;
1181 fmode = dos_mode(conn,fname,&sbuf);
1182 mtime = sbuf.st_mtime;
1184 close_file(fsp,False);
1185 END_PROFILE(SMBopenX);
1186 return ERROR_DOS(ERRDOS,ERRnoaccess);
1189 /* If the caller set the extended oplock request bit
1190 and we granted one (by whatever means) - set the
1191 correct bit for extended oplock reply.
1194 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1195 smb_action |= EXTENDED_OPLOCK_GRANTED;
1197 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1198 smb_action |= EXTENDED_OPLOCK_GRANTED;
1200 /* If the caller set the core oplock request bit
1201 and we granted one (by whatever means) - set the
1202 correct bit for core oplock reply.
1205 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1206 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1208 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1209 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1211 set_message(outbuf,15,0,True);
1212 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1213 SSVAL(outbuf,smb_vwv3,fmode);
1214 if(lp_dos_filetime_resolution(SNUM(conn)) )
1215 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1217 put_dos_date3(outbuf,smb_vwv4,mtime);
1218 SIVAL(outbuf,smb_vwv6,(uint32)size);
1219 SSVAL(outbuf,smb_vwv8,rmode);
1220 SSVAL(outbuf,smb_vwv11,smb_action);
1222 END_PROFILE(SMBopenX);
1223 return chain_reply(inbuf,outbuf,length,bufsize);
1226 /****************************************************************************
1227 Reply to a SMBulogoffX.
1228 ****************************************************************************/
1230 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1232 uint16 vuid = SVAL(inbuf,smb_uid);
1233 user_struct *vuser = get_valid_user_struct(vuid);
1234 START_PROFILE(SMBulogoffX);
1237 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1239 /* in user level security we are supposed to close any files
1240 open by this user */
1241 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1242 file_close_user(vuid);
1244 invalidate_vuid(vuid);
1246 set_message(outbuf,2,0,True);
1248 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1250 END_PROFILE(SMBulogoffX);
1251 return chain_reply(inbuf,outbuf,length,bufsize);
1254 /****************************************************************************
1255 Reply to a mknew or a create.
1256 ****************************************************************************/
1258 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1265 BOOL bad_path = False;
1267 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1268 SMB_STRUCT_STAT sbuf;
1270 START_PROFILE(SMBcreate);
1272 com = SVAL(inbuf,smb_com);
1274 createmode = SVAL(inbuf,smb_vwv0);
1275 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 END_PROFILE(SMBcreate);
1278 return ERROR_NT(status);
1281 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1283 unix_convert(fname,conn,0,&bad_path,&sbuf);
1285 END_PROFILE(SMBcreate);
1286 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1289 if (createmode & aVOLID)
1290 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1292 if(com == SMBmknew) {
1293 /* We should fail if file exists. */
1294 ofun = FILE_CREATE_IF_NOT_EXIST;
1296 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1297 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1300 /* Open file in dos compatibility share mode. */
1301 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1302 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1305 END_PROFILE(SMBcreate);
1306 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1307 /* We have re-scheduled this call. */
1308 clear_cached_errors();
1311 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1314 outsize = set_message(outbuf,1,0,True);
1315 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1317 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1318 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1320 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1321 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1323 DEBUG( 2, ( "new file %s\n", fname ) );
1324 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1326 END_PROFILE(SMBcreate);
1330 /****************************************************************************
1331 Reply to a create temporary file.
1332 ****************************************************************************/
1334 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1339 BOOL bad_path = False;
1341 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1343 SMB_STRUCT_STAT sbuf;
1346 unsigned int namelen;
1348 START_PROFILE(SMBctemp);
1350 createattr = SVAL(inbuf,smb_vwv0);
1351 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 END_PROFILE(SMBctemp);
1354 return ERROR_NT(status);
1357 pstrcat(fname,"/TMXXXXXX");
1359 pstrcat(fname,"TMXXXXXX");
1362 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1364 unix_convert(fname,conn,0,&bad_path,&sbuf);
1366 END_PROFILE(SMBctemp);
1367 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1370 tmpfd = smb_mkstemp(fname);
1372 END_PROFILE(SMBctemp);
1373 return(UNIXERROR(ERRDOS,ERRnoaccess));
1376 SMB_VFS_STAT(conn,fname,&sbuf);
1378 /* Open file in dos compatibility share mode. */
1379 /* We should fail if file does not exist. */
1380 fsp = open_file_shared(conn,fname,&sbuf,
1381 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1382 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1383 (uint32)createattr, oplock_request, NULL, NULL);
1385 /* close fd from smb_mkstemp() */
1389 END_PROFILE(SMBctemp);
1390 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1391 /* We have re-scheduled this call. */
1392 clear_cached_errors();
1395 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1398 outsize = set_message(outbuf,1,0,True);
1399 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1401 /* the returned filename is relative to the directory */
1402 s = strrchr_m(fname, '/');
1408 p = smb_buf(outbuf);
1410 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1411 thing in the byte section. JRA */
1412 SSVALS(p, 0, -1); /* what is this? not in spec */
1414 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1416 outsize = set_message_end(outbuf, p);
1418 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1419 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1421 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1422 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1424 DEBUG( 2, ( "created temp file %s\n", fname ) );
1425 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1426 fname, fsp->fd, sbuf.st_mode ) );
1428 END_PROFILE(SMBctemp);
1432 /*******************************************************************
1433 Check if a user is allowed to rename a file.
1434 ********************************************************************/
1436 static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
1443 if (!CAN_WRITE(conn))
1444 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1446 fmode = dos_mode(conn,fname,pst);
1447 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1448 return NT_STATUS_NO_SUCH_FILE;
1450 if (S_ISDIR(pst->st_mode))
1451 return NT_STATUS_OK;
1453 /* We need a better way to return NT status codes from open... */
1457 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1458 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1461 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1462 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1463 ret = NT_STATUS_SHARING_VIOLATION;
1466 unix_ERR_ntstatus = NT_STATUS_OK;
1469 close_file(fsp,False);
1470 return NT_STATUS_OK;
1473 /*******************************************************************
1474 Check if a user is allowed to delete a file.
1475 ********************************************************************/
1477 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1479 SMB_STRUCT_STAT sbuf;
1485 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1488 if (!CAN_WRITE(conn))
1489 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1491 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1492 if(errno == ENOENT) {
1494 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1496 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1498 return map_nt_error_from_unix(errno);
1501 fmode = dos_mode(conn,fname,&sbuf);
1503 /* Can't delete a directory. */
1505 return NT_STATUS_FILE_IS_A_DIRECTORY;
1507 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1508 return NT_STATUS_OBJECT_NAME_INVALID;
1509 #endif /* JRATEST */
1511 if (!lp_delete_readonly(SNUM(conn))) {
1513 return NT_STATUS_CANNOT_DELETE;
1515 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1516 return NT_STATUS_NO_SUCH_FILE;
1518 /* We need a better way to return NT status codes from open... */
1522 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1523 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1526 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1527 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1528 ret = unix_ERR_ntstatus;
1529 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1530 ret = NT_STATUS_SHARING_VIOLATION;
1533 unix_ERR_ntstatus = NT_STATUS_OK;
1536 close_file(fsp,False);
1537 return NT_STATUS_OK;
1540 /****************************************************************************
1541 The guts of the unlink command, split out so it may be called by the NT SMB
1543 ****************************************************************************/
1545 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1551 NTSTATUS error = NT_STATUS_OK;
1553 BOOL bad_path = False;
1555 SMB_STRUCT_STAT sbuf;
1557 *directory = *mask = 0;
1559 /* We must check for wildcards in the name given
1560 * directly by the client - before any unmangling.
1561 * This prevents an unmangling of a UNIX name containing
1562 * a DOS wildcard like '*' or '?' from unmangling into
1563 * a wildcard delete which was not intended.
1564 * FIX for #226. JRA.
1567 has_wild = ms_has_wild(name);
1569 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1571 p = strrchr_m(name,'/');
1573 pstrcpy(directory,".");
1577 pstrcpy(directory,name);
1582 * We should only check the mangled cache
1583 * here if unix_convert failed. This means
1584 * that the path in 'mask' doesn't exist
1585 * on the file system and so we need to look
1586 * for a possible mangle. This patch from
1587 * Tine Smukavec <valentin.smukavec@hermes.si>.
1590 if (!rc && mangle_is_mangled(mask))
1591 mangle_check_cache( mask, sizeof(pstring)-1 );
1594 pstrcat(directory,"/");
1595 pstrcat(directory,mask);
1596 error = can_delete(directory,conn,dirtype,bad_path);
1597 if (!NT_STATUS_IS_OK(error))
1600 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1604 void *dirptr = NULL;
1607 if (check_name(directory,conn))
1608 dirptr = OpenDir(conn, directory, True);
1610 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1611 the pattern matches against the long name, otherwise the short name
1612 We don't implement this yet XXXX
1616 error = NT_STATUS_NO_SUCH_FILE;
1619 if (strequal(mask,"????????.???"))
1622 while ((dname = ReadDirName(dirptr, &offset))) {
1624 BOOL sys_direntry = False;
1625 pstrcpy(fname,dname);
1627 /* Quick check for "." and ".." */
1628 if (fname[0] == '.') {
1629 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1630 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1631 sys_direntry = True;
1638 if(!mask_match(fname, mask, conn->case_sensitive))
1642 error = NT_STATUS_OBJECT_NAME_INVALID;
1643 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1648 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1649 error = can_delete(fname,conn,dirtype,bad_path);
1650 if (!NT_STATUS_IS_OK(error)) {
1653 if (SMB_VFS_UNLINK(conn,fname) == 0)
1655 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1661 if (count == 0 && NT_STATUS_IS_OK(error)) {
1662 error = map_nt_error_from_unix(errno);
1668 /****************************************************************************
1670 ****************************************************************************/
1672 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1679 START_PROFILE(SMBunlink);
1681 dirtype = SVAL(inbuf,smb_vwv0);
1683 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 END_PROFILE(SMBunlink);
1686 return ERROR_NT(status);
1689 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1691 DEBUG(3,("reply_unlink : %s\n",name));
1693 status = unlink_internals(conn, dirtype, name);
1694 if (!NT_STATUS_IS_OK(status)) {
1695 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1696 /* We have re-scheduled this call. */
1697 clear_cached_errors();
1700 return ERROR_NT(status);
1704 * Win2k needs a changenotify request response before it will
1705 * update after a rename..
1707 process_pending_change_notify_queue((time_t)0);
1709 outsize = set_message(outbuf,0,0,True);
1711 END_PROFILE(SMBunlink);
1715 /****************************************************************************
1717 ****************************************************************************/
1719 static void fail_readraw(void)
1722 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1724 exit_server(errstr);
1727 #if defined(WITH_SENDFILE)
1728 /****************************************************************************
1729 Fake (read/write) sendfile. Returns -1 on read or write fail.
1730 ****************************************************************************/
1732 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1736 /* Paranioa check... */
1737 if (nread > bufsize) {
1742 ret = read_file(fsp,buf,startpos,nread);
1748 /* If we had a short read, fill with zeros. */
1750 memset(buf, '\0', nread - ret);
1753 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1757 return (ssize_t)nread;
1761 /****************************************************************************
1762 Use sendfile in readbraw.
1763 ****************************************************************************/
1765 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1766 ssize_t mincount, char *outbuf, int out_buffsize)
1770 #if defined(WITH_SENDFILE)
1772 * We can only use sendfile on a non-chained packet
1773 * but we can use on a non-oplocked file. tridge proved this
1774 * on a train in Germany :-). JRA.
1775 * reply_readbraw has already checked the length.
1778 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1781 _smb_setlen(outbuf,nread);
1782 header.data = outbuf;
1786 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1787 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1788 if (errno == ENOSYS) {
1789 goto normal_readbraw;
1793 * Special hack for broken Linux with no working sendfile. If we
1794 * return EINTR we sent the header but not the rest of the data.
1795 * Fake this up by doing read/write calls.
1797 if (errno == EINTR) {
1798 /* Ensure we don't do this again. */
1799 set_use_sendfile(SNUM(conn), False);
1800 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1802 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1803 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1804 fsp->fsp_name, strerror(errno) ));
1805 exit_server("send_file_readbraw fake_sendfile failed");
1810 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1811 fsp->fsp_name, strerror(errno) ));
1812 exit_server("send_file_readbraw sendfile failed");
1822 ret = read_file(fsp,outbuf+4,startpos,nread);
1823 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1832 _smb_setlen(outbuf,ret);
1833 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1837 /****************************************************************************
1838 Reply to a readbraw (core+ protocol).
1839 ****************************************************************************/
1841 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1843 extern struct current_user current_user;
1844 ssize_t maxcount,mincount;
1847 char *header = outbuf;
1849 START_PROFILE(SMBreadbraw);
1851 if (srv_is_signing_active()) {
1852 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1856 * Special check if an oplock break has been issued
1857 * and the readraw request croses on the wire, we must
1858 * return a zero length response here.
1861 if(global_oplock_break) {
1862 _smb_setlen(header,0);
1863 if (write_data(smbd_server_fd(),header,4) != 4)
1865 DEBUG(5,("readbraw - oplock break finished\n"));
1866 END_PROFILE(SMBreadbraw);
1870 fsp = file_fsp(inbuf,smb_vwv0);
1872 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1874 * fsp could be NULL here so use the value from the packet. JRA.
1876 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1877 _smb_setlen(header,0);
1878 if (write_data(smbd_server_fd(),header,4) != 4)
1880 END_PROFILE(SMBreadbraw);
1884 CHECK_FSP(fsp,conn);
1886 flush_write_cache(fsp, READRAW_FLUSH);
1888 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1889 if(CVAL(inbuf,smb_wct) == 10) {
1891 * This is a large offset (64 bit) read.
1893 #ifdef LARGE_SMB_OFF_T
1895 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1897 #else /* !LARGE_SMB_OFF_T */
1900 * Ensure we haven't been sent a >32 bit offset.
1903 if(IVAL(inbuf,smb_vwv8) != 0) {
1904 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1905 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1906 _smb_setlen(header,0);
1907 if (write_data(smbd_server_fd(),header,4) != 4)
1909 END_PROFILE(SMBreadbraw);
1913 #endif /* LARGE_SMB_OFF_T */
1916 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1917 _smb_setlen(header,0);
1918 if (write_data(smbd_server_fd(),header,4) != 4)
1920 END_PROFILE(SMBreadbraw);
1924 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1925 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1927 /* ensure we don't overrun the packet size */
1928 maxcount = MIN(65535,maxcount);
1930 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
1931 SMB_OFF_T size = fsp->size;
1932 SMB_OFF_T sizeneeded = startpos + maxcount;
1934 if (size < sizeneeded) {
1936 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1938 if (!fsp->can_write)
1942 if (startpos >= size)
1945 nread = MIN(maxcount,(size - startpos));
1948 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1949 if (nread < mincount)
1953 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1954 (int)maxcount, (int)mincount, (int)nread ) );
1956 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
1958 DEBUG(5,("readbraw finished\n"));
1959 END_PROFILE(SMBreadbraw);
1963 /****************************************************************************
1964 Reply to a lockread (core+ protocol).
1965 ****************************************************************************/
1967 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1975 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1976 BOOL my_lock_ctx = False;
1977 START_PROFILE(SMBlockread);
1979 CHECK_FSP(fsp,conn);
1982 release_level_2_oplocks_on_change(fsp);
1984 numtoread = SVAL(inbuf,smb_vwv1);
1985 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1987 outsize = set_message(outbuf,5,3,True);
1988 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1989 data = smb_buf(outbuf) + 3;
1992 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1993 * protocol request that predates the read/write lock concept.
1994 * Thus instead of asking for a read lock here we need to ask
1995 * for a write lock. JRA.
1996 * Note that the requested lock size is unaffected by max_recv.
1999 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2000 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2002 if (NT_STATUS_V(status)) {
2005 * We used to make lockread a blocking lock. It turns out
2006 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2010 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2012 * A blocking lock was requested. Package up
2013 * this smb into a queued request and push it
2014 * onto the blocking lock queue.
2016 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2017 (SMB_BIG_UINT)numtoread)) {
2018 END_PROFILE(SMBlockread);
2023 END_PROFILE(SMBlockread);
2024 return ERROR_NT(status);
2028 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2031 if (numtoread > max_recv) {
2032 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2033 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2034 (unsigned int)numtoread, (unsigned int)max_recv ));
2035 numtoread = MIN(numtoread,max_recv);
2037 nread = read_file(fsp,data,startpos,numtoread);
2040 END_PROFILE(SMBlockread);
2041 return(UNIXERROR(ERRDOS,ERRnoaccess));
2045 SSVAL(outbuf,smb_vwv0,nread);
2046 SSVAL(outbuf,smb_vwv5,nread+3);
2047 SSVAL(smb_buf(outbuf),1,nread);
2049 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2050 fsp->fnum, (int)numtoread, (int)nread));
2052 END_PROFILE(SMBlockread);
2056 /****************************************************************************
2058 ****************************************************************************/
2060 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2067 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2068 START_PROFILE(SMBread);
2070 CHECK_FSP(fsp,conn);
2073 numtoread = SVAL(inbuf,smb_vwv1);
2074 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2076 outsize = set_message(outbuf,5,3,True);
2077 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2079 * The requested read size cannot be greater than max_recv. JRA.
2081 if (numtoread > max_recv) {
2082 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2083 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2084 (unsigned int)numtoread, (unsigned int)max_recv ));
2085 numtoread = MIN(numtoread,max_recv);
2088 data = smb_buf(outbuf) + 3;
2090 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2091 END_PROFILE(SMBread);
2092 return ERROR_DOS(ERRDOS,ERRlock);
2096 nread = read_file(fsp,data,startpos,numtoread);
2099 END_PROFILE(SMBread);
2100 return(UNIXERROR(ERRDOS,ERRnoaccess));
2104 SSVAL(outbuf,smb_vwv0,nread);
2105 SSVAL(outbuf,smb_vwv5,nread+3);
2106 SCVAL(smb_buf(outbuf),0,1);
2107 SSVAL(smb_buf(outbuf),1,nread);
2109 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2110 fsp->fnum, (int)numtoread, (int)nread ) );
2112 END_PROFILE(SMBread);
2116 /****************************************************************************
2117 Reply to a read and X - possibly using sendfile.
2118 ****************************************************************************/
2120 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2121 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2125 char *data = smb_buf(outbuf);
2127 #if defined(WITH_SENDFILE)
2129 * We can only use sendfile on a non-chained packet
2130 * but we can use on a non-oplocked file. tridge proved this
2131 * on a train in Germany :-). JRA.
2134 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2135 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2136 SMB_STRUCT_STAT sbuf;
2139 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2140 return(UNIXERROR(ERRDOS,ERRnoaccess));
2142 if (startpos > sbuf.st_size)
2145 if (smb_maxcnt > (sbuf.st_size - startpos))
2146 smb_maxcnt = (sbuf.st_size - startpos);
2148 if (smb_maxcnt == 0)
2152 * Set up the packet header before send. We
2153 * assume here the sendfile will work (get the
2154 * correct amount of data).
2157 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2158 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2159 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2160 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2161 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2162 SCVAL(outbuf,smb_vwv0,0xFF);
2163 set_message(outbuf,12,smb_maxcnt,False);
2164 header.data = outbuf;
2165 header.length = data - outbuf;
2168 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2169 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2170 if (errno == ENOSYS) {
2175 * Special hack for broken Linux with no working sendfile. If we
2176 * return EINTR we sent the header but not the rest of the data.
2177 * Fake this up by doing read/write calls.
2180 if (errno == EINTR) {
2181 /* Ensure we don't do this again. */
2182 set_use_sendfile(SNUM(conn), False);
2183 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2185 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2186 len_outbuf - (data-outbuf))) == -1) {
2187 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2188 fsp->fsp_name, strerror(errno) ));
2189 exit_server("send_file_readX: fake_sendfile failed");
2191 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2192 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2193 /* Returning -1 here means successful sendfile. */
2197 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2198 fsp->fsp_name, strerror(errno) ));
2199 exit_server("send_file_readX sendfile failed");
2202 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2203 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2204 /* Returning -1 here means successful sendfile. */
2212 nread = read_file(fsp,data,startpos,smb_maxcnt);
2215 END_PROFILE(SMBreadX);
2216 return(UNIXERROR(ERRDOS,ERRnoaccess));
2219 outsize = set_message(outbuf,12,nread,False);
2220 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2221 SSVAL(outbuf,smb_vwv5,nread);
2222 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2223 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2224 SSVAL(smb_buf(outbuf),-2,nread);
2226 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2227 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2229 /* Returning the number of bytes we want to send back - including header. */
2233 /****************************************************************************
2234 Reply to a read and X.
2235 ****************************************************************************/
2237 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2239 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2240 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2242 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2244 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2247 START_PROFILE(SMBreadX);
2249 /* If it's an IPC, pass off the pipe handler. */
2251 END_PROFILE(SMBreadX);
2252 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2255 CHECK_FSP(fsp,conn);
2258 set_message(outbuf,12,0,True);
2260 if (global_client_caps & CAP_LARGE_READX) {
2261 if (SVAL(inbuf,smb_vwv7) == 1) {
2262 smb_maxcnt |= (1<<16);
2264 if (smb_maxcnt > BUFFER_SIZE) {
2265 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2266 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2267 END_PROFILE(SMBreadX);
2268 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2272 if(CVAL(inbuf,smb_wct) == 12) {
2273 #ifdef LARGE_SMB_OFF_T
2275 * This is a large offset (64 bit) read.
2277 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2279 #else /* !LARGE_SMB_OFF_T */
2282 * Ensure we haven't been sent a >32 bit offset.
2285 if(IVAL(inbuf,smb_vwv10) != 0) {
2286 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2287 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2288 END_PROFILE(SMBreadX);
2289 return ERROR_DOS(ERRDOS,ERRbadaccess);
2292 #endif /* LARGE_SMB_OFF_T */
2296 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2297 END_PROFILE(SMBreadX);
2298 return ERROR_DOS(ERRDOS,ERRlock);
2301 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2303 nread = chain_reply(inbuf,outbuf,length,bufsize);
2305 END_PROFILE(SMBreadX);
2309 /****************************************************************************
2310 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2311 ****************************************************************************/
2313 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2316 ssize_t total_written=0;
2317 size_t numtowrite=0;
2322 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2324 START_PROFILE(SMBwritebraw);
2326 if (srv_is_signing_active()) {
2327 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2330 CHECK_FSP(fsp,conn);
2333 tcount = IVAL(inbuf,smb_vwv1);
2334 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2335 write_through = BITSETW(inbuf+smb_vwv7,0);
2337 /* We have to deal with slightly different formats depending
2338 on whether we are using the core+ or lanman1.0 protocol */
2340 if(Protocol <= PROTOCOL_COREPLUS) {
2341 numtowrite = SVAL(smb_buf(inbuf),-2);
2342 data = smb_buf(inbuf);
2344 numtowrite = SVAL(inbuf,smb_vwv10);
2345 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2348 /* force the error type */
2349 SCVAL(inbuf,smb_com,SMBwritec);
2350 SCVAL(outbuf,smb_com,SMBwritec);
2352 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2353 END_PROFILE(SMBwritebraw);
2354 return(ERROR_DOS(ERRDOS,ERRlock));
2358 nwritten = write_file(fsp,data,startpos,numtowrite);
2360 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2361 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2363 if (nwritten < (ssize_t)numtowrite) {
2364 END_PROFILE(SMBwritebraw);
2365 return(UNIXERROR(ERRHRD,ERRdiskfull));
2368 total_written = nwritten;
2370 /* Return a message to the redirector to tell it to send more bytes */
2371 SCVAL(outbuf,smb_com,SMBwritebraw);
2372 SSVALS(outbuf,smb_vwv0,-1);
2373 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2374 if (!send_smb(smbd_server_fd(),outbuf))
2375 exit_server("reply_writebraw: send_smb failed.");
2377 /* Now read the raw data into the buffer and write it */
2378 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2379 exit_server("secondary writebraw failed");
2382 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2383 numtowrite = smb_len(inbuf);
2385 /* Set up outbuf to return the correct return */
2386 outsize = set_message(outbuf,1,0,True);
2387 SCVAL(outbuf,smb_com,SMBwritec);
2388 SSVAL(outbuf,smb_vwv0,total_written);
2390 if (numtowrite != 0) {
2392 if (numtowrite > BUFFER_SIZE) {
2393 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2394 (unsigned int)numtowrite ));
2395 exit_server("secondary writebraw failed");
2398 if (tcount > nwritten+numtowrite) {
2399 DEBUG(3,("Client overestimated the write %d %d %d\n",
2400 (int)tcount,(int)nwritten,(int)numtowrite));
2403 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2404 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2406 exit_server("secondary writebraw failed");
2409 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2411 if (nwritten < (ssize_t)numtowrite) {
2412 SCVAL(outbuf,smb_rcls,ERRHRD);
2413 SSVAL(outbuf,smb_err,ERRdiskfull);
2417 total_written += nwritten;
2420 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2421 sync_file(conn,fsp);
2423 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2424 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2426 /* we won't return a status if write through is not selected - this follows what WfWg does */
2427 END_PROFILE(SMBwritebraw);
2428 if (!write_through && total_written==tcount) {
2430 #if RABBIT_PELLET_FIX
2432 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2433 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2435 if (!send_keepalive(smbd_server_fd()))
2436 exit_server("reply_writebraw: send of keepalive failed");
2444 /****************************************************************************
2445 Reply to a writeunlock (core+).
2446 ****************************************************************************/
2448 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2449 int size, int dum_buffsize)
2451 ssize_t nwritten = -1;
2455 NTSTATUS status = NT_STATUS_OK;
2456 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2458 START_PROFILE(SMBwriteunlock);
2460 CHECK_FSP(fsp,conn);
2463 numtowrite = SVAL(inbuf,smb_vwv1);
2464 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2465 data = smb_buf(inbuf) + 3;
2467 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2468 END_PROFILE(SMBwriteunlock);
2469 return ERROR_DOS(ERRDOS,ERRlock);
2472 /* The special X/Open SMB protocol handling of
2473 zero length writes is *NOT* done for
2478 nwritten = write_file(fsp,data,startpos,numtowrite);
2480 if (lp_syncalways(SNUM(conn)))
2481 sync_file(conn,fsp);
2483 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2484 END_PROFILE(SMBwriteunlock);
2485 return(UNIXERROR(ERRHRD,ERRdiskfull));
2489 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2490 (SMB_BIG_UINT)startpos);
2491 if (NT_STATUS_V(status)) {
2492 END_PROFILE(SMBwriteunlock);
2493 return ERROR_NT(status);
2497 outsize = set_message(outbuf,1,0,True);
2499 SSVAL(outbuf,smb_vwv0,nwritten);
2501 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2502 fsp->fnum, (int)numtowrite, (int)nwritten));
2504 END_PROFILE(SMBwriteunlock);
2508 /****************************************************************************
2510 ****************************************************************************/
2512 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2515 ssize_t nwritten = -1;
2518 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2520 START_PROFILE(SMBwrite);
2522 /* If it's an IPC, pass off the pipe handler. */
2524 END_PROFILE(SMBwrite);
2525 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2528 CHECK_FSP(fsp,conn);
2531 numtowrite = SVAL(inbuf,smb_vwv1);
2532 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2533 data = smb_buf(inbuf) + 3;
2535 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2536 END_PROFILE(SMBwrite);
2537 return ERROR_DOS(ERRDOS,ERRlock);
2541 * X/Open SMB protocol says that if smb_vwv1 is
2542 * zero then the file size should be extended or
2543 * truncated to the size given in smb_vwv[2-3].
2546 if(numtowrite == 0) {
2548 * This is actually an allocate call, and set EOF. JRA.
2550 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2552 END_PROFILE(SMBwrite);
2553 return ERROR_NT(NT_STATUS_DISK_FULL);
2555 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2557 END_PROFILE(SMBwrite);
2558 return ERROR_NT(NT_STATUS_DISK_FULL);
2561 nwritten = write_file(fsp,data,startpos,numtowrite);
2563 if (lp_syncalways(SNUM(conn)))
2564 sync_file(conn,fsp);
2566 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2567 END_PROFILE(SMBwrite);
2568 return(UNIXERROR(ERRHRD,ERRdiskfull));
2571 outsize = set_message(outbuf,1,0,True);
2573 SSVAL(outbuf,smb_vwv0,nwritten);
2575 if (nwritten < (ssize_t)numtowrite) {
2576 SCVAL(outbuf,smb_rcls,ERRHRD);
2577 SSVAL(outbuf,smb_err,ERRdiskfull);
2580 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2582 END_PROFILE(SMBwrite);
2586 /****************************************************************************
2587 Reply to a write and X.
2588 ****************************************************************************/
2590 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2592 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2593 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2594 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2595 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2596 ssize_t nwritten = -1;
2597 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2598 unsigned int smblen = smb_len(inbuf);
2600 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2601 START_PROFILE(SMBwriteX);
2603 /* If it's an IPC, pass off the pipe handler. */
2605 END_PROFILE(SMBwriteX);
2606 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2609 CHECK_FSP(fsp,conn);
2612 /* Deal with possible LARGE_WRITEX */
2614 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2616 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2617 END_PROFILE(SMBwriteX);
2618 return ERROR_DOS(ERRDOS,ERRbadmem);
2621 data = smb_base(inbuf) + smb_doff;
2623 if(CVAL(inbuf,smb_wct) == 14) {
2624 #ifdef LARGE_SMB_OFF_T
2626 * This is a large offset (64 bit) write.
2628 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2630 #else /* !LARGE_SMB_OFF_T */
2633 * Ensure we haven't been sent a >32 bit offset.
2636 if(IVAL(inbuf,smb_vwv12) != 0) {
2637 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2638 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2639 END_PROFILE(SMBwriteX);
2640 return ERROR_DOS(ERRDOS,ERRbadaccess);
2643 #endif /* LARGE_SMB_OFF_T */
2646 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2647 END_PROFILE(SMBwriteX);
2648 return ERROR_DOS(ERRDOS,ERRlock);
2651 /* X/Open SMB protocol says that, unlike SMBwrite
2652 if the length is zero then NO truncation is
2653 done, just a write of zero. To truncate a file,
2659 nwritten = write_file(fsp,data,startpos,numtowrite);
2661 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2662 END_PROFILE(SMBwriteX);
2663 return(UNIXERROR(ERRHRD,ERRdiskfull));
2666 set_message(outbuf,6,0,True);
2668 SSVAL(outbuf,smb_vwv2,nwritten);
2670 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2672 if (nwritten < (ssize_t)numtowrite) {
2673 SCVAL(outbuf,smb_rcls,ERRHRD);
2674 SSVAL(outbuf,smb_err,ERRdiskfull);
2677 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2678 fsp->fnum, (int)numtowrite, (int)nwritten));
2680 if (lp_syncalways(SNUM(conn)) || write_through)
2681 sync_file(conn,fsp);
2683 END_PROFILE(SMBwriteX);
2684 return chain_reply(inbuf,outbuf,length,bufsize);
2687 /****************************************************************************
2689 ****************************************************************************/
2691 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2697 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2698 START_PROFILE(SMBlseek);
2700 CHECK_FSP(fsp,conn);
2702 flush_write_cache(fsp, SEEK_FLUSH);
2704 mode = SVAL(inbuf,smb_vwv1) & 3;
2705 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2706 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2715 res = fsp->pos + startpos;
2726 if (umode == SEEK_END) {
2727 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2728 if(errno == EINVAL) {
2729 SMB_OFF_T current_pos = startpos;
2730 SMB_STRUCT_STAT sbuf;
2732 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2733 END_PROFILE(SMBlseek);
2734 return(UNIXERROR(ERRDOS,ERRnoaccess));
2737 current_pos += sbuf.st_size;
2739 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2744 END_PROFILE(SMBlseek);
2745 return(UNIXERROR(ERRDOS,ERRnoaccess));
2751 outsize = set_message(outbuf,2,0,True);
2752 SIVAL(outbuf,smb_vwv0,res);
2754 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2755 fsp->fnum, (double)startpos, (double)res, mode));
2757 END_PROFILE(SMBlseek);
2761 /****************************************************************************
2763 ****************************************************************************/
2765 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2767 int outsize = set_message(outbuf,0,0,True);
2768 uint16 fnum = SVAL(inbuf,smb_vwv0);
2769 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2770 START_PROFILE(SMBflush);
2773 CHECK_FSP(fsp,conn);
2776 file_sync_all(conn);
2778 sync_file(conn,fsp);
2781 DEBUG(3,("flush\n"));
2782 END_PROFILE(SMBflush);
2786 /****************************************************************************
2788 ****************************************************************************/
2790 int reply_exit(connection_struct *conn,
2791 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2794 START_PROFILE(SMBexit);
2796 file_close_pid(SVAL(inbuf,smb_pid));
2798 outsize = set_message(outbuf,0,0,True);
2800 DEBUG(3,("exit\n"));
2802 END_PROFILE(SMBexit);
2806 /****************************************************************************
2807 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2808 ****************************************************************************/
2810 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2813 extern struct current_user current_user;
2816 int32 eclass = 0, err = 0;
2817 files_struct *fsp = NULL;
2818 START_PROFILE(SMBclose);
2820 outsize = set_message(outbuf,0,0,True);
2822 /* If it's an IPC, pass off to the pipe handler. */
2824 END_PROFILE(SMBclose);
2825 return reply_pipe_close(conn, inbuf,outbuf);
2828 fsp = file_fsp(inbuf,smb_vwv0);
2831 * We can only use CHECK_FSP if we know it's not a directory.
2834 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2835 END_PROFILE(SMBclose);
2836 return ERROR_DOS(ERRDOS,ERRbadfid);
2839 if(fsp->is_directory) {
2841 * Special case - close NT SMB directory handle.
2843 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2844 close_file(fsp,True);
2847 * Close ordinary file.
2852 /* Save the name for time set in close. */
2853 pstrcpy( file_name, fsp->fsp_name);
2855 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2857 conn->num_files_open));
2860 * close_file() returns the unix errno if an error
2861 * was detected on close - normally this is due to
2862 * a disk full error. If not then it was probably an I/O error.
2865 if((close_err = close_file(fsp,True)) != 0) {
2867 END_PROFILE(SMBclose);
2868 return (UNIXERROR(ERRHRD,ERRgeneral));
2872 * Now take care of any time sent in the close.
2875 mtime = make_unix_date3(inbuf+smb_vwv1);
2877 /* try and set the date */
2878 set_filetime(conn, file_name, mtime);
2882 /* We have a cached error */
2884 END_PROFILE(SMBclose);
2885 return ERROR_DOS(eclass,err);
2888 END_PROFILE(SMBclose);
2892 /****************************************************************************
2893 Reply to a writeclose (Core+ protocol).
2894 ****************************************************************************/
2896 int reply_writeclose(connection_struct *conn,
2897 char *inbuf,char *outbuf, int size, int dum_buffsize)
2900 ssize_t nwritten = -1;
2906 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2907 START_PROFILE(SMBwriteclose);
2909 CHECK_FSP(fsp,conn);
2912 numtowrite = SVAL(inbuf,smb_vwv1);
2913 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2914 mtime = make_unix_date3(inbuf+smb_vwv4);
2915 data = smb_buf(inbuf) + 1;
2917 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2918 END_PROFILE(SMBwriteclose);
2919 return ERROR_DOS(ERRDOS,ERRlock);
2922 nwritten = write_file(fsp,data,startpos,numtowrite);
2924 set_filetime(conn, fsp->fsp_name,mtime);
2927 * More insanity. W2K only closes the file if writelen > 0.
2932 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2934 close_err = close_file(fsp,True);
2937 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2938 fsp->fnum, (int)numtowrite, (int)nwritten,
2939 conn->num_files_open));
2941 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2942 END_PROFILE(SMBwriteclose);
2943 return(UNIXERROR(ERRHRD,ERRdiskfull));
2946 if(close_err != 0) {
2948 END_PROFILE(SMBwriteclose);
2949 return(UNIXERROR(ERRHRD,ERRgeneral));
2952 outsize = set_message(outbuf,1,0,True);
2954 SSVAL(outbuf,smb_vwv0,nwritten);
2955 END_PROFILE(SMBwriteclose);
2959 /****************************************************************************
2961 ****************************************************************************/
2963 int reply_lock(connection_struct *conn,
2964 char *inbuf,char *outbuf, int length, int dum_buffsize)
2966 int outsize = set_message(outbuf,0,0,True);
2967 SMB_BIG_UINT count,offset;
2969 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2970 BOOL my_lock_ctx = False;
2972 START_PROFILE(SMBlock);
2974 CHECK_FSP(fsp,conn);
2976 release_level_2_oplocks_on_change(fsp);
2978 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2979 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2981 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2982 fsp->fd, fsp->fnum, (double)offset, (double)count));
2984 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2985 if (NT_STATUS_V(status)) {
2987 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2988 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2990 * A blocking lock was requested. Package up
2991 * this smb into a queued request and push it
2992 * onto the blocking lock queue.
2994 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2995 END_PROFILE(SMBlock);
3000 END_PROFILE(SMBlock);
3001 return ERROR_NT(status);
3004 END_PROFILE(SMBlock);
3008 /****************************************************************************
3010 ****************************************************************************/
3012 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3015 int outsize = set_message(outbuf,0,0,True);
3016 SMB_BIG_UINT count,offset;
3018 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3019 START_PROFILE(SMBunlock);
3021 CHECK_FSP(fsp,conn);
3023 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3024 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3026 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3027 if (NT_STATUS_V(status)) {
3028 END_PROFILE(SMBunlock);
3029 return ERROR_NT(status);
3032 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3033 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3035 END_PROFILE(SMBunlock);
3039 /****************************************************************************
3041 ****************************************************************************/
3043 int reply_tdis(connection_struct *conn,
3044 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3046 int outsize = set_message(outbuf,0,0,True);
3048 START_PROFILE(SMBtdis);
3050 vuid = SVAL(inbuf,smb_uid);
3053 DEBUG(4,("Invalid connection in tdis\n"));
3054 END_PROFILE(SMBtdis);
3055 return ERROR_DOS(ERRSRV,ERRinvnid);
3060 close_cnum(conn,vuid);
3062 END_PROFILE(SMBtdis);
3066 /****************************************************************************
3068 ****************************************************************************/
3070 int reply_echo(connection_struct *conn,
3071 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3073 int smb_reverb = SVAL(inbuf,smb_vwv0);
3075 unsigned int data_len = smb_buflen(inbuf);
3076 int outsize = set_message(outbuf,1,data_len,True);
3077 START_PROFILE(SMBecho);
3079 if (data_len > BUFFER_SIZE) {
3080 DEBUG(0,("reply_echo: data_len too large.\n"));
3081 END_PROFILE(SMBecho);
3085 /* copy any incoming data back out */
3087 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3089 if (smb_reverb > 100) {
3090 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3094 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3095 SSVAL(outbuf,smb_vwv0,seq_num);
3097 smb_setlen(outbuf,outsize - 4);
3099 if (!send_smb(smbd_server_fd(),outbuf))
3100 exit_server("reply_echo: send_smb failed.");
3103 DEBUG(3,("echo %d times\n", smb_reverb));
3107 END_PROFILE(SMBecho);
3111 /****************************************************************************
3112 Reply to a printopen.
3113 ****************************************************************************/
3115 int reply_printopen(connection_struct *conn,
3116 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3120 START_PROFILE(SMBsplopen);
3122 if (!CAN_PRINT(conn)) {
3123 END_PROFILE(SMBsplopen);
3124 return ERROR_DOS(ERRDOS,ERRnoaccess);
3127 /* Open for exclusive use, write only. */
3128 fsp = print_fsp_open(conn, NULL);
3131 END_PROFILE(SMBsplopen);
3132 return(UNIXERROR(ERRDOS,ERRnoaccess));
3135 outsize = set_message(outbuf,1,0,True);
3136 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3138 DEBUG(3,("openprint fd=%d fnum=%d\n",
3139 fsp->fd, fsp->fnum));
3141 END_PROFILE(SMBsplopen);
3145 /****************************************************************************
3146 Reply to a printclose.
3147 ****************************************************************************/
3149 int reply_printclose(connection_struct *conn,
3150 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3152 int outsize = set_message(outbuf,0,0,True);
3153 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3155 START_PROFILE(SMBsplclose);
3157 CHECK_FSP(fsp,conn);
3159 if (!CAN_PRINT(conn)) {
3160 END_PROFILE(SMBsplclose);
3161 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3164 DEBUG(3,("printclose fd=%d fnum=%d\n",
3165 fsp->fd,fsp->fnum));
3167 close_err = close_file(fsp,True);
3169 if(close_err != 0) {
3171 END_PROFILE(SMBsplclose);
3172 return(UNIXERROR(ERRHRD,ERRgeneral));
3175 END_PROFILE(SMBsplclose);
3179 /****************************************************************************
3180 Reply to a printqueue.
3181 ****************************************************************************/
3183 int reply_printqueue(connection_struct *conn,
3184 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3186 int outsize = set_message(outbuf,2,3,True);
3187 int max_count = SVAL(inbuf,smb_vwv0);
3188 int start_index = SVAL(inbuf,smb_vwv1);
3189 START_PROFILE(SMBsplretq);
3191 /* we used to allow the client to get the cnum wrong, but that
3192 is really quite gross and only worked when there was only
3193 one printer - I think we should now only accept it if they
3194 get it right (tridge) */
3195 if (!CAN_PRINT(conn)) {
3196 END_PROFILE(SMBsplretq);
3197 return ERROR_DOS(ERRDOS,ERRnoaccess);
3200 SSVAL(outbuf,smb_vwv0,0);
3201 SSVAL(outbuf,smb_vwv1,0);
3202 SCVAL(smb_buf(outbuf),0,1);
3203 SSVAL(smb_buf(outbuf),1,0);
3205 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3206 start_index, max_count));
3209 print_queue_struct *queue = NULL;
3210 print_status_struct status;
3211 char *p = smb_buf(outbuf) + 3;
3212 int count = print_queue_status(SNUM(conn), &queue, &status);
3213 int num_to_get = ABS(max_count);
3214 int first = (max_count>0?start_index:start_index+max_count+1);
3220 num_to_get = MIN(num_to_get,count-first);
3223 for (i=first;i<first+num_to_get;i++) {
3224 put_dos_date2(p,0,queue[i].time);
3225 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3226 SSVAL(p,5, queue[i].job);
3227 SIVAL(p,7,queue[i].size);
3229 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3234 outsize = set_message(outbuf,2,28*count+3,False);
3235 SSVAL(outbuf,smb_vwv0,count);
3236 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3237 SCVAL(smb_buf(outbuf),0,1);
3238 SSVAL(smb_buf(outbuf),1,28*count);
3243 DEBUG(3,("%d entries returned in queue\n",count));
3246 END_PROFILE(SMBsplretq);
3250 /****************************************************************************
3251 Reply to a printwrite.
3252 ****************************************************************************/
3254 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3257 int outsize = set_message(outbuf,0,0,True);
3259 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3261 START_PROFILE(SMBsplwr);
3263 if (!CAN_PRINT(conn)) {
3264 END_PROFILE(SMBsplwr);
3265 return ERROR_DOS(ERRDOS,ERRnoaccess);
3268 CHECK_FSP(fsp,conn);
3271 numtowrite = SVAL(smb_buf(inbuf),1);
3272 data = smb_buf(inbuf) + 3;
3274 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3275 END_PROFILE(SMBsplwr);
3276 return(UNIXERROR(ERRHRD,ERRdiskfull));
3279 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3281 END_PROFILE(SMBsplwr);
3285 /****************************************************************************
3286 The guts of the mkdir command, split out so it may be called by the NT SMB
3288 ****************************************************************************/
3290 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3292 BOOL bad_path = False;
3293 SMB_STRUCT_STAT sbuf;
3296 unix_convert(directory,conn,0,&bad_path,&sbuf);
3298 if( strchr_m(directory, ':')) {
3299 return NT_STATUS_NOT_A_DIRECTORY;
3302 if (ms_has_wild(directory)) {
3303 return NT_STATUS_OBJECT_NAME_INVALID;
3307 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3310 if (check_name(directory, conn))
3311 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3314 if(errno == ENOENT) {
3315 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3317 return map_nt_error_from_unix(errno);
3320 return NT_STATUS_OK;
3323 /****************************************************************************
3325 ****************************************************************************/
3327 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3332 START_PROFILE(SMBmkdir);
3334 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3335 if (!NT_STATUS_IS_OK(status)) {
3336 END_PROFILE(SMBmkdir);
3337 return ERROR_NT(status);
3340 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3342 status = mkdir_internal(conn, directory);
3343 if (!NT_STATUS_IS_OK(status)) {
3344 END_PROFILE(SMBmkdir);
3345 return ERROR_NT(status);
3348 outsize = set_message(outbuf,0,0,True);
3350 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3352 END_PROFILE(SMBmkdir);
3356 /****************************************************************************
3357 Static function used by reply_rmdir to delete an entire directory
3358 tree recursively. Return False on ok, True on fail.
3359 ****************************************************************************/
3361 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3363 const char *dname = NULL;
3366 void *dirptr = OpenDir(conn, directory, False);
3371 while((dname = ReadDirName(dirptr, &offset))) {
3375 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3378 /* Construct the full name. */
3379 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3385 pstrcpy(fullname, directory);
3386 pstrcat(fullname, "/");
3387 pstrcat(fullname, dname);
3389 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3394 if(st.st_mode & S_IFDIR) {
3395 if(recursive_rmdir(conn, fullname)!=0) {
3399 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3403 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3412 /****************************************************************************
3413 The internals of the rmdir code - called elsewhere.
3414 ****************************************************************************/
3416 BOOL rmdir_internals(connection_struct *conn, char *directory)
3420 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3421 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3423 * Check to see if the only thing in this directory are
3424 * vetoed files/directories. If so then delete them and
3425 * retry. If we fail to delete any of them (and we *don't*
3426 * do a recursive delete) then fail the rmdir.
3428 BOOL all_veto_files = True;
3430 void *dirptr = OpenDir(conn, directory, False);
3432 if(dirptr != NULL) {
3433 long dirpos = TellDir(dirptr);
3434 while ((dname = ReadDirName(dirptr,&dirpos))) {
3435 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3437 if(!IS_VETO_PATH(conn, dname)) {
3438 all_veto_files = False;
3443 if(all_veto_files) {
3444 SeekDir(dirptr,dirpos);
3445 while ((dname = ReadDirName(dirptr,&dirpos))) {
3449 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3452 /* Construct the full name. */
3453 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3458 pstrcpy(fullname, directory);
3459 pstrcat(fullname, "/");
3460 pstrcat(fullname, dname);
3462 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3464 if(st.st_mode & S_IFDIR) {
3465 if(lp_recursive_veto_delete(SNUM(conn))) {
3466 if(recursive_rmdir(conn, fullname) != 0)
3469 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3471 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3475 /* Retry the rmdir */
3476 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3486 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3491 /****************************************************************************
3493 ****************************************************************************/
3495 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3500 BOOL bad_path = False;
3501 SMB_STRUCT_STAT sbuf;
3503 START_PROFILE(SMBrmdir);
3505 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 END_PROFILE(SMBrmdir);
3508 return ERROR_NT(status);
3511 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3513 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3515 END_PROFILE(SMBrmdir);
3516 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3519 if (check_name(directory,conn)) {
3520 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3521 ok = rmdir_internals(conn, directory);
3525 END_PROFILE(SMBrmdir);
3526 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3529 outsize = set_message(outbuf,0,0,True);
3531 DEBUG( 3, ( "rmdir %s\n", directory ) );
3533 END_PROFILE(SMBrmdir);
3537 /*******************************************************************
3538 Resolve wildcards in a filename rename.
3539 Note that name is in UNIX charset and thus potentially can be more
3540 than fstring buffer (255 bytes) especially in default UTF-8 case.
3541 Therefore, we use pstring inside and all calls should ensure that
3542 name2 is at least pstring-long (they do already)
3543 ********************************************************************/
3545 static BOOL resolve_wildcards(const char *name1, char *name2)
3547 pstring root1,root2;
3549 char *p,*p2, *pname1, *pname2;
3550 int available_space, actual_space;
3553 pname1 = strrchr_m(name1,'/');
3554 pname2 = strrchr_m(name2,'/');
3556 if (!pname1 || !pname2)
3559 pstrcpy(root1,pname1);
3560 pstrcpy(root2,pname2);
3561 p = strrchr_m(root1,'.');
3568 p = strrchr_m(root2,'.');
3582 } else if (*p2 == '*') {
3598 } else if (*p2 == '*') {
3608 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3611 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3612 if (actual_space >= available_space - 1) {
3613 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3614 actual_space - available_space));
3617 pstrcpy_base(pname2, root2, name2);
3623 /****************************************************************************
3624 Ensure open files have their names updates.
3625 ****************************************************************************/
3627 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3630 BOOL did_rename = False;
3632 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3633 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3634 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3635 fsp->fsp_name, newname ));
3636 string_set(&fsp->fsp_name, newname);
3641 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3642 (unsigned int)dev, (double)inode, newname ));
3645 /****************************************************************************
3646 Rename an open file - given an fsp.
3647 ****************************************************************************/
3649 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3651 SMB_STRUCT_STAT sbuf;
3652 BOOL bad_path = False;
3653 pstring newname_last_component;
3654 NTSTATUS error = NT_STATUS_OK;
3659 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3661 /* Quick check for "." and ".." */
3662 if (!bad_path && newname_last_component[0] == '.') {
3663 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3664 return NT_STATUS_ACCESS_DENIED;
3667 if (!rcdest && bad_path) {
3668 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3671 /* Ensure newname contains a '/' */
3672 if(strrchr_m(newname,'/') == 0) {
3675 pstrcpy(tmpstr, "./");
3676 pstrcat(tmpstr, newname);
3677 pstrcpy(newname, tmpstr);
3681 * Check for special case with case preserving and not
3682 * case sensitive. If the old last component differs from the original
3683 * last component only by case, then we should allow
3684 * the rename (user is trying to change the case of the
3688 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3689 strequal(newname, fsp->fsp_name)) {
3691 pstring newname_modified_last_component;
3694 * Get the last component of the modified name.
3695 * Note that we guarantee that newname contains a '/'
3698 p = strrchr_m(newname,'/');
3699 pstrcpy(newname_modified_last_component,p+1);
3701 if(strcsequal(newname_modified_last_component,
3702 newname_last_component) == False) {
3704 * Replace the modified last component with
3707 pstrcpy(p+1, newname_last_component);
3712 * If the src and dest names are identical - including case,
3713 * don't do the rename, just return success.
3716 if (strcsequal(fsp->fsp_name, newname)) {
3717 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3719 return NT_STATUS_OK;
3722 dest_exists = vfs_object_exist(conn,newname,NULL);
3724 if(!replace_if_exists && dest_exists) {
3725 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3726 fsp->fsp_name,newname));
3727 return NT_STATUS_OBJECT_NAME_COLLISION;
3730 error = can_rename(newname,conn,attrs,&sbuf);
3732 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3733 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3734 nt_errstr(error), fsp->fsp_name,newname));
3735 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3736 error = NT_STATUS_ACCESS_DENIED;
3740 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3741 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3742 fsp->fsp_name,newname));
3743 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3744 return NT_STATUS_OK;
3747 if (errno == ENOTDIR || errno == EISDIR)
3748 error = NT_STATUS_OBJECT_NAME_COLLISION;
3750 error = map_nt_error_from_unix(errno);
3752 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3753 nt_errstr(error), fsp->fsp_name,newname));
3758 /****************************************************************************
3759 The guts of the rename command, split out so it may be called by the NT SMB
3761 ****************************************************************************/
3763 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3767 pstring last_component_src;
3768 pstring last_component_dest;
3771 BOOL bad_path_src = False;
3772 BOOL bad_path_dest = False;
3774 NTSTATUS error = NT_STATUS_OK;
3777 SMB_STRUCT_STAT sbuf1, sbuf2;
3779 *directory = *mask = 0;
3784 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3785 if (!rc && bad_path_src) {
3786 if (ms_has_wild(last_component_src))
3787 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3788 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3791 /* Quick check for "." and ".." */
3792 if (last_component_src[0] == '.') {
3793 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3794 return NT_STATUS_OBJECT_NAME_INVALID;
3798 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3800 /* Quick check for "." and ".." */
3801 if (last_component_dest[0] == '.') {
3802 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3803 return NT_STATUS_OBJECT_NAME_INVALID;
3808 * Split the old name into directory and last component
3809 * strings. Note that unix_convert may have stripped off a
3810 * leading ./ from both name and newname if the rename is
3811 * at the root of the share. We need to make sure either both
3812 * name and newname contain a / character or neither of them do
3813 * as this is checked in resolve_wildcards().
3816 p = strrchr_m(name,'/');
3818 pstrcpy(directory,".");
3822 pstrcpy(directory,name);
3824 *p = '/'; /* Replace needed for exceptional test below. */
3828 * We should only check the mangled cache
3829 * here if unix_convert failed. This means
3830 * that the path in 'mask' doesn't exist
3831 * on the file system and so we need to look
3832 * for a possible mangle. This patch from
3833 * Tine Smukavec <valentin.smukavec@hermes.si>.
3836 if (!rc && mangle_is_mangled(mask))
3837 mangle_check_cache( mask, sizeof(pstring)-1 );
3839 has_wild = ms_has_wild(mask);
3843 * No wildcards - just process the one file.
3845 BOOL is_short_name = mangle_is_8_3(name, True);
3847 /* Add a terminating '/' to the directory name. */
3848 pstrcat(directory,"/");
3849 pstrcat(directory,mask);
3851 /* Ensure newname contains a '/' also */
3852 if(strrchr_m(newname,'/') == 0) {
3855 pstrcpy(tmpstr, "./");
3856 pstrcat(tmpstr, newname);
3857 pstrcpy(newname, tmpstr);
3860 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3861 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3862 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3863 newname, last_component_dest, is_short_name));
3866 * Check for special case with case preserving and not
3867 * case sensitive, if directory and newname are identical,
3868 * and the old last component differs from the original
3869 * last component only by case, then we should allow
3870 * the rename (user is trying to change the case of the
3873 if((conn->case_sensitive == False) &&
3874 (((conn->case_preserve == True) &&
3875 (is_short_name == False)) ||
3876 ((conn->short_case_preserve == True) &&
3877 (is_short_name == True))) &&
3878 strcsequal(directory, newname)) {
3879 pstring modified_last_component;
3882 * Get the last component of the modified name.
3883 * Note that we guarantee that newname contains a '/'
3886 p = strrchr_m(newname,'/');
3887 pstrcpy(modified_last_component,p+1);
3889 if(strcsequal(modified_last_component,
3890 last_component_dest) == False) {
3892 * Replace the modified last component with
3895 pstrcpy(p+1, last_component_dest);
3899 resolve_wildcards(directory,newname);
3902 * The source object must exist.
3905 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3906 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3907 directory,newname));
3909 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3911 * Must return different errors depending on whether the parent
3912 * directory existed or not.
3915 p = strrchr_m(directory, '/');
3917 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3919 if (vfs_object_exist(conn, directory, NULL))
3920 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3921 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3923 error = map_nt_error_from_unix(errno);
3924 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3925 nt_errstr(error), directory,newname));
3930 if (!rcdest && bad_path_dest) {
3931 if (ms_has_wild(last_component_dest))
3932 return NT_STATUS_OBJECT_NAME_INVALID;
3933 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3936 error = can_rename(directory,conn,attrs,&sbuf1);
3938 if (!NT_STATUS_IS_OK(error)) {
3939 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3940 nt_errstr(error), directory,newname));
3945 * If the src and dest names are identical - including case,
3946 * don't do the rename, just return success.
3949 if (strcsequal(directory, newname)) {
3950 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3951 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3952 return NT_STATUS_OK;
3955 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3956 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3957 directory,newname));
3958 return NT_STATUS_OBJECT_NAME_COLLISION;
3961 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3962 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3963 directory,newname));
3964 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3965 return NT_STATUS_OK;
3968 if (errno == ENOTDIR || errno == EISDIR)
3969 error = NT_STATUS_OBJECT_NAME_COLLISION;
3971 error = map_nt_error_from_unix(errno);
3973 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3974 nt_errstr(error), directory,newname));
3979 * Wildcards - process each file that matches.
3981 void *dirptr = NULL;
3985 if (check_name(directory,conn))
3986 dirptr = OpenDir(conn, directory, True);
3990 error = NT_STATUS_NO_SUCH_FILE;
3991 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3993 if (strequal(mask,"????????.???"))
3996 while ((dname = ReadDirName(dirptr, &offset))) {
3998 BOOL sysdir_entry = False;
4000 pstrcpy(fname,dname);
4002 /* Quick check for "." and ".." */
4003 if (fname[0] == '.') {
4004 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4006 sysdir_entry = True;
4013 if(!mask_match(fname, mask, conn->case_sensitive))
4017 error = NT_STATUS_OBJECT_NAME_INVALID;
4021 error = NT_STATUS_ACCESS_DENIED;
4022 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4023 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4024 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4025 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4028 error = can_rename(fname,conn,attrs,&sbuf1);
4029 if (!NT_STATUS_IS_OK(error)) {
4030 DEBUG(6,("rename %s refused\n", fname));
4033 pstrcpy(destname,newname);
4035 if (!resolve_wildcards(fname,destname)) {
4036 DEBUG(6,("resolve_wildcards %s %s failed\n",
4041 if (strcsequal(fname,destname)) {
4042 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4043 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4045 error = NT_STATUS_OK;
4049 if (!replace_if_exists &&
4050 vfs_file_exist(conn,destname, NULL)) {
4051 DEBUG(6,("file_exist %s\n", destname));
4052 error = NT_STATUS_OBJECT_NAME_COLLISION;
4056 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4057 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4059 error = NT_STATUS_OK;
4061 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4066 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4067 if (!rcdest && bad_path_dest) {
4068 if (ms_has_wild(last_component_dest))
4069 return NT_STATUS_OBJECT_NAME_INVALID;
4070 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4075 if (count == 0 && NT_STATUS_IS_OK(error)) {
4076 error = map_nt_error_from_unix(errno);
4082 /****************************************************************************
4084 ****************************************************************************/
4086 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4093 uint16 attrs = SVAL(inbuf,smb_vwv0);
4096 START_PROFILE(SMBmv);
4098 p = smb_buf(inbuf) + 1;
4099 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4100 if (!NT_STATUS_IS_OK(status)) {
4102 return ERROR_NT(status);
4105 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4106 if (!NT_STATUS_IS_OK(status)) {
4108 return ERROR_NT(status);
4111 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4112 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4114 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4116 status = rename_internals(conn, name, newname, attrs, False);
4117 if (!NT_STATUS_IS_OK(status)) {
4119 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4120 /* We have re-scheduled this call. */
4121 clear_cached_errors();
4124 return ERROR_NT(status);
4128 * Win2k needs a changenotify request response before it will
4129 * update after a rename..
4131 process_pending_change_notify_queue((time_t)0);
4132 outsize = set_message(outbuf,0,0,True);
4138 /*******************************************************************
4139 Copy a file as part of a reply_copy.
4140 ******************************************************************/
4142 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4143 int count,BOOL target_is_directory, int *err_ret)
4146 SMB_STRUCT_STAT src_sbuf, sbuf2;
4148 files_struct *fsp1,*fsp2;
4154 pstrcpy(dest,dest1);
4155 if (target_is_directory) {
4156 char *p = strrchr_m(src,'/');
4165 if (!vfs_file_exist(conn,src,&src_sbuf))
4168 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4169 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4175 if (!target_is_directory && count)
4176 ofun = FILE_EXISTS_OPEN;
4178 dosattrs = dos_mode(conn, src, &src_sbuf);
4179 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4180 ZERO_STRUCTP(&sbuf2);
4182 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4183 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4186 close_file(fsp1,False);
4190 if ((ofun&3) == 1) {
4191 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4192 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4194 * Stop the copy from occurring.
4197 src_sbuf.st_size = 0;
4201 if (src_sbuf.st_size)
4202 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4204 close_file(fsp1,False);
4206 /* Ensure the modtime is set correctly on the destination file. */
4207 fsp2->pending_modtime = src_sbuf.st_mtime;
4210 * As we are opening fsp1 read-only we only expect
4211 * an error on close on fsp2 if we are out of space.
4212 * Thus we don't look at the error return from the
4215 *err_ret = close_file(fsp2,False);
4217 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4220 /****************************************************************************
4221 Reply to a file copy.
4222 ****************************************************************************/
4224 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4229 pstring mask,newname;
4232 int error = ERRnoaccess;
4236 int tid2 = SVAL(inbuf,smb_vwv0);
4237 int ofun = SVAL(inbuf,smb_vwv1);
4238 int flags = SVAL(inbuf,smb_vwv2);
4239 BOOL target_is_directory=False;
4240 BOOL bad_path1 = False;
4241 BOOL bad_path2 = False;
4243 SMB_STRUCT_STAT sbuf1, sbuf2;
4246 START_PROFILE(SMBcopy);
4248 *directory = *mask = 0;
4251 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4252 if (!NT_STATUS_IS_OK(status)) {
4253 END_PROFILE(SMBcopy);
4254 return ERROR_NT(status);
4256 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4257 if (!NT_STATUS_IS_OK(status)) {
4258 END_PROFILE(SMBcopy);
4259 return ERROR_NT(status);
4262 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4264 if (tid2 != conn->cnum) {
4265 /* can't currently handle inter share copies XXXX */
4266 DEBUG(3,("Rejecting inter-share copy\n"));
4267 END_PROFILE(SMBcopy);
4268 return ERROR_DOS(ERRSRV,ERRinvdevice);
4271 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4272 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4274 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4275 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4277 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4279 if ((flags&1) && target_is_directory) {
4280 END_PROFILE(SMBcopy);
4281 return ERROR_DOS(ERRDOS,ERRbadfile);
4284 if ((flags&2) && !target_is_directory) {
4285 END_PROFILE(SMBcopy);
4286 return ERROR_DOS(ERRDOS,ERRbadpath);
4289 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4290 /* wants a tree copy! XXXX */
4291 DEBUG(3,("Rejecting tree copy\n"));
4292 END_PROFILE(SMBcopy);
4293 return ERROR_DOS(ERRSRV,ERRerror);
4296 p = strrchr_m(name,'/');
4298 pstrcpy(directory,"./");
4302 pstrcpy(directory,name);
4307 * We should only check the mangled cache
4308 * here if unix_convert failed. This means
4309 * that the path in 'mask' doesn't exist
4310 * on the file system and so we need to look
4311 * for a possible mangle. This patch from
4312 * Tine Smukavec <valentin.smukavec@hermes.si>.
4315 if (!rc && mangle_is_mangled(mask))
4316 mangle_check_cache( mask, sizeof(pstring)-1 );
4318 has_wild = ms_has_wild(mask);
4321 pstrcat(directory,"/");
4322 pstrcat(directory,mask);
4323 if (resolve_wildcards(directory,newname) &&
4324 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4328 END_PROFILE(SMBcopy);
4329 return(UNIXERROR(ERRHRD,ERRgeneral));
4332 exists = vfs_file_exist(conn,directory,NULL);
4335 void *dirptr = NULL;
4339 if (check_name(directory,conn))
4340 dirptr = OpenDir(conn, directory, True);
4346 if (strequal(mask,"????????.???"))
4349 while ((dname = ReadDirName(dirptr, &offset))) {
4351 pstrcpy(fname,dname);
4353 if(!mask_match(fname, mask, conn->case_sensitive))
4356 error = ERRnoaccess;
4357 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4358 pstrcpy(destname,newname);
4359 if (resolve_wildcards(fname,destname) &&
4360 copy_file(fname,destname,conn,ofun,
4361 count,target_is_directory,&err))
4363 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4371 /* Error on close... */
4373 END_PROFILE(SMBcopy);
4374 return(UNIXERROR(ERRHRD,ERRgeneral));
4378 END_PROFILE(SMBcopy);
4379 return ERROR_DOS(ERRDOS,error);
4381 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4382 unix_ERR_class = ERRDOS;
4383 unix_ERR_code = ERRbadpath;
4385 END_PROFILE(SMBcopy);
4386 return(UNIXERROR(ERRDOS,error));
4390 outsize = set_message(outbuf,1,0,True);
4391 SSVAL(outbuf,smb_vwv0,count);
4393 END_PROFILE(SMBcopy);
4397 /****************************************************************************
4399 ****************************************************************************/
4401 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4409 START_PROFILE(pathworks_setdir);
4412 if (!CAN_SETDIR(snum)) {
4413 END_PROFILE(pathworks_setdir);
4414 return ERROR_DOS(ERRDOS,ERRnoaccess);
4417 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4418 if (!NT_STATUS_IS_OK(status)) {
4419 END_PROFILE(pathworks_setdir);
4420 return ERROR_NT(status);
4423 if (strlen(newdir) == 0) {
4426 ok = vfs_directory_exist(conn,newdir,NULL);
4428 string_set(&conn->connectpath,newdir);
4432 END_PROFILE(pathworks_setdir);
4433 return ERROR_DOS(ERRDOS,ERRbadpath);
4436 outsize = set_message(outbuf,0,0,True);
4437 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4439 DEBUG(3,("setdir %s\n", newdir));
4441 END_PROFILE(pathworks_setdir);
4445 /****************************************************************************
4446 Get a lock pid, dealing with large count requests.
4447 ****************************************************************************/
4449 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4451 if(!large_file_format)
4452 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4454 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4457 /****************************************************************************
4458 Get a lock count, dealing with large count requests.
4459 ****************************************************************************/
4461 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4463 SMB_BIG_UINT count = 0;
4465 if(!large_file_format) {
4466 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4469 #if defined(HAVE_LONGLONG)
4470 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4471 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4472 #else /* HAVE_LONGLONG */
4475 * NT4.x seems to be broken in that it sends large file (64 bit)
4476 * lockingX calls even if the CAP_LARGE_FILES was *not*
4477 * negotiated. For boxes without large unsigned ints truncate the
4478 * lock count by dropping the top 32 bits.
4481 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4482 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4483 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4484 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4485 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4488 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4489 #endif /* HAVE_LONGLONG */
4495 #if !defined(HAVE_LONGLONG)
4496 /****************************************************************************
4497 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4498 ****************************************************************************/
4500 static uint32 map_lock_offset(uint32 high, uint32 low)
4504 uint32 highcopy = high;
4507 * Try and find out how many significant bits there are in high.
4510 for(i = 0; highcopy; i++)
4514 * We use 31 bits not 32 here as POSIX
4515 * lock offsets may not be negative.
4518 mask = (~0) << (31 - i);
4521 return 0; /* Fail. */
4527 #endif /* !defined(HAVE_LONGLONG) */
4529 /****************************************************************************
4530 Get a lock offset, dealing with large offset requests.
4531 ****************************************************************************/
4533 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4535 SMB_BIG_UINT offset = 0;
4539 if(!large_file_format) {
4540 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4543 #if defined(HAVE_LONGLONG)
4544 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4545 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4546 #else /* HAVE_LONGLONG */
4549 * NT4.x seems to be broken in that it sends large file (64 bit)
4550 * lockingX calls even if the CAP_LARGE_FILES was *not*
4551 * negotiated. For boxes without large unsigned ints mangle the
4552 * lock offset by mapping the top 32 bits onto the lower 32.
4555 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4556 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4557 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4560 if((new_low = map_lock_offset(high, low)) == 0) {
4562 return (SMB_BIG_UINT)-1;
4565 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4566 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4567 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4568 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4571 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4572 #endif /* HAVE_LONGLONG */
4578 /****************************************************************************
4579 Reply to a lockingX request.
4580 ****************************************************************************/
4582 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4584 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4585 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4586 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4587 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4588 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4589 SMB_BIG_UINT count = 0, offset = 0;
4591 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4594 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4596 BOOL my_lock_ctx = False;
4599 START_PROFILE(SMBlockingX);
4601 CHECK_FSP(fsp,conn);
4603 data = smb_buf(inbuf);
4605 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4606 /* we don't support these - and CANCEL_LOCK makes w2k
4607 and XP reboot so I don't really want to be
4608 compatible! (tridge) */
4609 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4612 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4613 /* Need to make this like a cancel.... JRA. */
4614 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4617 /* Check if this is an oplock break on a file
4618 we have granted an oplock on.
4620 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4621 /* Client can insist on breaking to none. */
4622 BOOL break_to_none = (oplocklevel == 0);
4624 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4625 (unsigned int)oplocklevel, fsp->fnum ));
4628 * Make sure we have granted an exclusive or batch oplock on this file.
4631 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4632 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4633 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4635 /* if this is a pure oplock break request then don't send a reply */
4636 if (num_locks == 0 && num_ulocks == 0) {
4637 END_PROFILE(SMBlockingX);
4640 END_PROFILE(SMBlockingX);
4641 return ERROR_DOS(ERRDOS,ERRlock);
4645 if (remove_oplock(fsp, break_to_none) == False) {
4646 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4650 /* if this is a pure oplock break request then don't send a reply */
4651 if (num_locks == 0 && num_ulocks == 0) {
4652 /* Sanity check - ensure a pure oplock break is not a
4654 if(CVAL(inbuf,smb_vwv0) != 0xff)
4655 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4656 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4657 END_PROFILE(SMBlockingX);
4663 * We do this check *after* we have checked this is not a oplock break
4664 * response message. JRA.
4667 release_level_2_oplocks_on_change(fsp);
4669 /* Data now points at the beginning of the list
4670 of smb_unlkrng structs */
4671 for(i = 0; i < (int)num_ulocks; i++) {
4672 lock_pid = get_lock_pid( data, i, large_file_format);
4673 count = get_lock_count( data, i, large_file_format);
4674 offset = get_lock_offset( data, i, large_file_format, &err);
4677 * There is no error code marked "stupid client bug".... :-).
4680 END_PROFILE(SMBlockingX);
4681 return ERROR_DOS(ERRDOS,ERRnoaccess);
4684 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4685 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4687 status = do_unlock(fsp,conn,lock_pid,count,offset);
4688 if (NT_STATUS_V(status)) {
4689 END_PROFILE(SMBlockingX);
4690 return ERROR_NT(status);
4694 /* Setup the timeout in seconds. */
4696 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4698 /* Now do any requested locks */
4699 data += ((large_file_format ? 20 : 10)*num_ulocks);
4701 /* Data now points at the beginning of the list
4702 of smb_lkrng structs */
4704 for(i = 0; i < (int)num_locks; i++) {
4705 lock_pid = get_lock_pid( data, i, large_file_format);
4706 count = get_lock_count( data, i, large_file_format);
4707 offset = get_lock_offset( data, i, large_file_format, &err);
4710 * There is no error code marked "stupid client bug".... :-).
4713 END_PROFILE(SMBlockingX);
4714 return ERROR_DOS(ERRDOS,ERRnoaccess);
4717 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4718 (double)offset, (double)count, (unsigned int)lock_pid,
4719 fsp->fsp_name, (int)lock_timeout ));
4721 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4722 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4723 if (NT_STATUS_V(status)) {
4725 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4726 * Even if it's our own lock context, we need to wait here as
4727 * there may be an unlock on the way.
4728 * So I removed a "&& !my_lock_ctx" from the following
4729 * if statement. JRA.
4731 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4733 * A blocking lock was requested. Package up
4734 * this smb into a queued request and push it
4735 * onto the blocking lock queue.
4737 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4738 END_PROFILE(SMBlockingX);
4746 /* If any of the above locks failed, then we must unlock
4747 all of the previous locks (X/Open spec). */
4748 if (i != num_locks && num_locks != 0) {
4750 * Ensure we don't do a remove on the lock that just failed,
4751 * as under POSIX rules, if we have a lock already there, we
4752 * will delete it (and we shouldn't) .....
4754 for(i--; i >= 0; i--) {
4755 lock_pid = get_lock_pid( data, i, large_file_format);
4756 count = get_lock_count( data, i, large_file_format);
4757 offset = get_lock_offset( data, i, large_file_format, &err);
4760 * There is no error code marked "stupid client bug".... :-).
4763 END_PROFILE(SMBlockingX);
4764 return ERROR_DOS(ERRDOS,ERRnoaccess);
4767 do_unlock(fsp,conn,lock_pid,count,offset);
4769 END_PROFILE(SMBlockingX);
4770 return ERROR_NT(status);
4773 set_message(outbuf,2,0,True);
4775 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4776 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4778 END_PROFILE(SMBlockingX);
4779 return chain_reply(inbuf,outbuf,length,bufsize);
4782 /****************************************************************************
4783 Reply to a SMBreadbmpx (read block multiplex) request.
4784 ****************************************************************************/
4786 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4797 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4798 START_PROFILE(SMBreadBmpx);
4800 /* this function doesn't seem to work - disable by default */
4801 if (!lp_readbmpx()) {
4802 END_PROFILE(SMBreadBmpx);
4803 return ERROR_DOS(ERRSRV,ERRuseSTD);
4806 outsize = set_message(outbuf,8,0,True);
4808 CHECK_FSP(fsp,conn);
4811 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4812 maxcount = SVAL(inbuf,smb_vwv3);
4814 data = smb_buf(outbuf);
4815 pad = ((long)data)%4;
4820 max_per_packet = bufsize-(outsize+pad);
4824 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4825 END_PROFILE(SMBreadBmpx);
4826 return ERROR_DOS(ERRDOS,ERRlock);
4830 size_t N = MIN(max_per_packet,tcount-total_read);
4832 nread = read_file(fsp,data,startpos,N);
4837 if (nread < (ssize_t)N)
4838 tcount = total_read + nread;
4840 set_message(outbuf,8,nread,False);
4841 SIVAL(outbuf,smb_vwv0,startpos);
4842 SSVAL(outbuf,smb_vwv2,tcount);
4843 SSVAL(outbuf,smb_vwv6,nread);
4844 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4846 if (!send_smb(smbd_server_fd(),outbuf))
4847 exit_server("reply_readbmpx: send_smb failed.");
4849 total_read += nread;
4851 } while (total_read < (ssize_t)tcount);
4853 END_PROFILE(SMBreadBmpx);
4857 /****************************************************************************
4858 Reply to a SMBsetattrE.
4859 ****************************************************************************/
4861 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4863 struct utimbuf unix_times;
4865 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4866 START_PROFILE(SMBsetattrE);
4868 outsize = set_message(outbuf,0,0,True);
4870 if(!fsp || (fsp->conn != conn)) {
4871 END_PROFILE(SMBgetattrE);
4872 return ERROR_DOS(ERRDOS,ERRbadfid);
4876 * Convert the DOS times into unix times. Ignore create
4877 * time as UNIX can't set this.
4880 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4881 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4884 * Patch from Ray Frush <frush@engr.colostate.edu>
4885 * Sometimes times are sent as zero - ignore them.
4888 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4889 /* Ignore request */
4890 if( DEBUGLVL( 3 ) ) {
4891 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4892 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4894 END_PROFILE(SMBsetattrE);
4896 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4897 /* set modify time = to access time if modify time was 0 */
4898 unix_times.modtime = unix_times.actime;
4901 /* Set the date on this file */
4902 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4903 END_PROFILE(SMBsetattrE);
4904 return ERROR_DOS(ERRDOS,ERRnoaccess);
4907 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4908 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4910 END_PROFILE(SMBsetattrE);
4915 /* Back from the dead for OS/2..... JRA. */
4917 /****************************************************************************
4918 Reply to a SMBwritebmpx (write block multiplex primary) request.
4919 ****************************************************************************/
4921 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4924 ssize_t nwritten = -1;
4931 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4932 START_PROFILE(SMBwriteBmpx);
4934 CHECK_FSP(fsp,conn);
4938 tcount = SVAL(inbuf,smb_vwv1);
4939 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4940 write_through = BITSETW(inbuf+smb_vwv7,0);
4941 numtowrite = SVAL(inbuf,smb_vwv10);
4942 smb_doff = SVAL(inbuf,smb_vwv11);
4944 data = smb_base(inbuf) + smb_doff;
4946 /* If this fails we need to send an SMBwriteC response,
4947 not an SMBwritebmpx - set this up now so we don't forget */
4948 SCVAL(outbuf,smb_com,SMBwritec);
4950 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4951 END_PROFILE(SMBwriteBmpx);
4952 return(ERROR_DOS(ERRDOS,ERRlock));
4955 nwritten = write_file(fsp,data,startpos,numtowrite);
4957 if(lp_syncalways(SNUM(conn)) || write_through)
4958 sync_file(conn,fsp);
4960 if(nwritten < (ssize_t)numtowrite) {
4961 END_PROFILE(SMBwriteBmpx);
4962 return(UNIXERROR(ERRHRD,ERRdiskfull));
4965 /* If the maximum to be written to this file
4966 is greater than what we just wrote then set
4967 up a secondary struct to be attached to this
4968 fd, we will use this to cache error messages etc. */
4970 if((ssize_t)tcount > nwritten) {
4971 write_bmpx_struct *wbms;
4972 if(fsp->wbmpx_ptr != NULL)
4973 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4975 wbms = SMB_MALLOC_P(write_bmpx_struct);
4977 DEBUG(0,("Out of memory in reply_readmpx\n"));
4978 END_PROFILE(SMBwriteBmpx);
4979 return(ERROR_DOS(ERRSRV,ERRnoresource));
4981 wbms->wr_mode = write_through;
4982 wbms->wr_discard = False; /* No errors yet */
4983 wbms->wr_total_written = nwritten;
4984 wbms->wr_errclass = 0;
4986 fsp->wbmpx_ptr = wbms;
4989 /* We are returning successfully, set the message type back to
4991 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4993 outsize = set_message(outbuf,1,0,True);
4995 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4997 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4998 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5000 if (write_through && tcount==nwritten) {
5001 /* We need to send both a primary and a secondary response */
5002 smb_setlen(outbuf,outsize - 4);
5003 if (!send_smb(smbd_server_fd(),outbuf))
5004 exit_server("reply_writebmpx: send_smb failed.");
5006 /* Now the secondary */
5007 outsize = set_message(outbuf,1,0,True);
5008 SCVAL(outbuf,smb_com,SMBwritec);
5009 SSVAL(outbuf,smb_vwv0,nwritten);
5012 END_PROFILE(SMBwriteBmpx);
5016 /****************************************************************************
5017 Reply to a SMBwritebs (write block multiplex secondary) request.
5018 ****************************************************************************/
5020 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5023 ssize_t nwritten = -1;
5030 write_bmpx_struct *wbms;
5031 BOOL send_response = False;
5032 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5033 START_PROFILE(SMBwriteBs);
5035 CHECK_FSP(fsp,conn);
5038 tcount = SVAL(inbuf,smb_vwv1);
5039 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5040 numtowrite = SVAL(inbuf,smb_vwv6);
5041 smb_doff = SVAL(inbuf,smb_vwv7);
5043 data = smb_base(inbuf) + smb_doff;
5045 /* We need to send an SMBwriteC response, not an SMBwritebs */
5046 SCVAL(outbuf,smb_com,SMBwritec);
5048 /* This fd should have an auxiliary struct attached,
5049 check that it does */
5050 wbms = fsp->wbmpx_ptr;
5052 END_PROFILE(SMBwriteBs);
5056 /* If write through is set we can return errors, else we must cache them */
5057 write_through = wbms->wr_mode;
5059 /* Check for an earlier error */
5060 if(wbms->wr_discard) {
5061 END_PROFILE(SMBwriteBs);
5062 return -1; /* Just discard the packet */
5065 nwritten = write_file(fsp,data,startpos,numtowrite);
5067 if(lp_syncalways(SNUM(conn)) || write_through)
5068 sync_file(conn,fsp);
5070 if (nwritten < (ssize_t)numtowrite) {
5072 /* We are returning an error - we can delete the aux struct */
5075 fsp->wbmpx_ptr = NULL;
5076 END_PROFILE(SMBwriteBs);
5077 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5079 END_PROFILE(SMBwriteBs);
5080 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5083 /* Increment the total written, if this matches tcount
5084 we can discard the auxiliary struct (hurrah !) and return a writeC */
5085 wbms->wr_total_written += nwritten;
5086 if(wbms->wr_total_written >= tcount) {
5087 if (write_through) {
5088 outsize = set_message(outbuf,1,0,True);
5089 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5090 send_response = True;
5094 fsp->wbmpx_ptr = NULL;
5098 END_PROFILE(SMBwriteBs);
5102 END_PROFILE(SMBwriteBs);
5106 /****************************************************************************
5107 Reply to a SMBgetattrE.
5108 ****************************************************************************/
5110 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5112 SMB_STRUCT_STAT sbuf;
5115 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5116 START_PROFILE(SMBgetattrE);
5118 outsize = set_message(outbuf,11,0,True);
5120 if(!fsp || (fsp->conn != conn)) {
5121 END_PROFILE(SMBgetattrE);
5122 return ERROR_DOS(ERRDOS,ERRbadfid);
5125 /* Do an fstat on this file */
5126 if(fsp_stat(fsp, &sbuf)) {
5127 END_PROFILE(SMBgetattrE);
5128 return(UNIXERROR(ERRDOS,ERRnoaccess));
5131 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5134 * Convert the times into dos times. Set create
5135 * date to be last modify date as UNIX doesn't save
5139 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5140 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5141 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5144 SIVAL(outbuf,smb_vwv6,0);
5145 SIVAL(outbuf,smb_vwv8,0);
5147 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5148 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5149 SIVAL(outbuf,smb_vwv8,allocation_size);
5151 SSVAL(outbuf,smb_vwv10, mode);
5153 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5155 END_PROFILE(SMBgetattrE);