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 */
33 extern char magic_char;
34 extern int global_oplock_break;
35 unsigned int smb_echo_count = 0;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
49 const char *s = srcname;
50 NTSTATUS ret = NT_STATUS_OK;
53 if (IS_DIRECTORY_SEP(*s)) {
55 * Safe to assume is not the second part of a mb char as this is handled below.
57 /* Eat multiple '/' or '\\' */
58 while (IS_DIRECTORY_SEP(*s)) {
61 if ((s[0] == '.') && (s[1] == '\0')) {
62 ret = NT_STATUS_OBJECT_NAME_INVALID;
65 if ((d != destname) && (*s != '\0')) {
66 /* We only care about non-leading or trailing '/' or '\\' */
69 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
70 /* Uh oh - "../" or "..\\" or "..\0" ! */
73 * No mb char starts with '.' so we're safe checking the directory separator here.
76 /* If we just added a '/', delete it. */
78 if ((d > destname) && (*(d-1) == '/')) {
80 if (d == (destname + 1)) {
86 /* Are we at the start ? Can't go back further if so. */
88 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
91 /* Go back one level... */
92 /* We know this is safe as '/' cannot be part of a mb sequence. */
93 /* NOTE - if this assumption is invalid we are not in good shape... */
94 while (d > destname) {
100 } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) {
103 * No mb char starts with '.' so we're safe checking the directory separator here.
106 /* "./" or ".\\" fails with a different error depending on where it is... */
109 ret = NT_STATUS_OBJECT_NAME_INVALID;
112 if (s[1] != '\0' && s[2] == '\0') {
113 ret = NT_STATUS_INVALID_PARAMETER;
116 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
122 if (allow_wcard_names) {
131 return NT_STATUS_OBJECT_NAME_INVALID;
138 switch(next_mb_char_size(s)) {
149 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
151 return NT_STATUS_INVALID_PARAMETER;
160 /****************************************************************************
161 Pull a string and check the path - provide for error return.
162 ****************************************************************************/
164 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)
167 char *tmppath_ptr = tmppath;
170 SMB_ASSERT(dest_len == sizeof(pstring));
174 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
176 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
178 *err = check_path_syntax(dest, tmppath, allow_wcard_names);
182 /****************************************************************************
183 Reply to a special message.
184 ****************************************************************************/
186 int reply_special(char *inbuf,char *outbuf)
189 int msg_type = CVAL(inbuf,0);
190 int msg_flags = CVAL(inbuf,1);
194 static BOOL already_got_session = False;
198 memset(outbuf,'\0',smb_size);
200 smb_setlen(outbuf,0);
203 case 0x81: /* session request */
205 if (already_got_session) {
206 exit_server("multiple session request not permitted");
209 SCVAL(outbuf,0,0x82);
211 if (name_len(inbuf+4) > 50 ||
212 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
213 DEBUG(0,("Invalid name length in session request\n"));
216 name_extract(inbuf,4,name1);
217 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
218 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
221 set_local_machine_name(name1, True);
222 set_remote_machine_name(name2, True);
224 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
225 get_local_machine_name(), get_remote_machine_name(),
228 if (name_type == 'R') {
229 /* We are being asked for a pathworks session ---
231 SCVAL(outbuf, 0,0x83);
235 /* only add the client's machine name to the list
236 of possibly valid usernames if we are operating
237 in share mode security */
238 if (lp_security() == SEC_SHARE) {
239 add_session_user(get_remote_machine_name());
242 reload_services(True);
245 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
247 already_got_session = True;
250 case 0x89: /* session keepalive request
251 (some old clients produce this?) */
252 SCVAL(outbuf,0,SMBkeepalive);
256 case 0x82: /* positive session response */
257 case 0x83: /* negative session response */
258 case 0x84: /* retarget session response */
259 DEBUG(0,("Unexpected session response\n"));
262 case SMBkeepalive: /* session keepalive */
267 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
268 msg_type, msg_flags));
273 /****************************************************************************
275 ****************************************************************************/
277 int reply_tcon(connection_struct *conn,
278 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
285 uint16 vuid = SVAL(inbuf,smb_uid);
289 DATA_BLOB password_blob;
291 START_PROFILE(SMBtcon);
293 *service_buf = *password = *dev = 0;
295 p = smb_buf(inbuf)+1;
296 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
297 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
299 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
301 p = strrchr_m(service_buf,'\\');
305 service = service_buf;
308 password_blob = data_blob(password, pwlen+1);
310 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
312 data_blob_clear_free(&password_blob);
315 END_PROFILE(SMBtcon);
316 return ERROR_NT(nt_status);
319 outsize = set_message(outbuf,2,0,True);
320 SSVAL(outbuf,smb_vwv0,max_recv);
321 SSVAL(outbuf,smb_vwv1,conn->cnum);
322 SSVAL(outbuf,smb_tid,conn->cnum);
324 DEBUG(3,("tcon service=%s cnum=%d\n",
325 service, conn->cnum));
327 END_PROFILE(SMBtcon);
331 /****************************************************************************
332 Reply to a tcon and X.
333 ****************************************************************************/
335 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
340 /* what the cleint thinks the device is */
341 fstring client_devicetype;
342 /* what the server tells the client the share represents */
343 const char *server_devicetype;
345 uint16 vuid = SVAL(inbuf,smb_uid);
346 int passlen = SVAL(inbuf,smb_vwv3);
349 extern BOOL global_encrypted_passwords_negotiated;
351 START_PROFILE(SMBtconX);
353 *service = *client_devicetype = 0;
355 /* we might have to close an old one */
356 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
357 close_cnum(conn,vuid);
360 if (passlen > MAX_PASS_LEN) {
361 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
364 if (global_encrypted_passwords_negotiated) {
365 password = data_blob(smb_buf(inbuf),passlen);
367 password = data_blob(smb_buf(inbuf),passlen+1);
368 /* Ensure correct termination */
369 password.data[passlen]=0;
372 p = smb_buf(inbuf) + passlen;
373 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
376 * the service name can be either: \\server\share
377 * or share directly like on the DELL PowerVault 705
380 q = strchr_m(path+2,'\\');
382 END_PROFILE(SMBtconX);
383 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
385 fstrcpy(service,q+1);
388 fstrcpy(service,path);
390 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
392 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
394 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
396 data_blob_clear_free(&password);
399 END_PROFILE(SMBtconX);
400 return ERROR_NT(nt_status);
404 server_devicetype = "IPC";
405 else if ( IS_PRINT(conn) )
406 server_devicetype = "LPT1:";
408 server_devicetype = "A:";
410 if (Protocol < PROTOCOL_NT1) {
411 set_message(outbuf,2,0,True);
413 p += srvstr_push(outbuf, p, server_devicetype, -1,
414 STR_TERMINATE|STR_ASCII);
415 set_message_end(outbuf,p);
417 /* NT sets the fstype of IPC$ to the null string */
418 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
420 set_message(outbuf,3,0,True);
423 p += srvstr_push(outbuf, p, server_devicetype, -1,
424 STR_TERMINATE|STR_ASCII);
425 p += srvstr_push(outbuf, p, fstype, -1,
428 set_message_end(outbuf,p);
430 /* what does setting this bit do? It is set by NT4 and
431 may affect the ability to autorun mounted cdroms */
432 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
433 (lp_csc_policy(SNUM(conn)) << 2));
435 init_dfsroot(conn, inbuf, outbuf);
439 DEBUG(3,("tconX service=%s \n",
442 /* set the incoming and outgoing tid to the just created one */
443 SSVAL(inbuf,smb_tid,conn->cnum);
444 SSVAL(outbuf,smb_tid,conn->cnum);
446 END_PROFILE(SMBtconX);
447 return chain_reply(inbuf,outbuf,length,bufsize);
450 /****************************************************************************
451 Reply to an unknown type.
452 ****************************************************************************/
454 int reply_unknown(char *inbuf,char *outbuf)
457 type = CVAL(inbuf,smb_com);
459 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
460 smb_fn_name(type), type, type));
462 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
465 /****************************************************************************
467 ****************************************************************************/
469 int reply_ioctl(connection_struct *conn,
470 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
472 uint16 device = SVAL(inbuf,smb_vwv1);
473 uint16 function = SVAL(inbuf,smb_vwv2);
474 uint32 ioctl_code = (device << 16) + function;
475 int replysize, outsize;
477 START_PROFILE(SMBioctl);
479 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
481 switch (ioctl_code) {
482 case IOCTL_QUERY_JOB_INFO:
486 END_PROFILE(SMBioctl);
487 return(ERROR_DOS(ERRSRV,ERRnosupport));
490 outsize = set_message(outbuf,8,replysize+1,True);
491 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
492 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
493 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
494 p = smb_buf(outbuf) + 1; /* Allow for alignment */
496 switch (ioctl_code) {
497 case IOCTL_QUERY_JOB_INFO:
499 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
501 END_PROFILE(SMBioctl);
502 return(UNIXERROR(ERRDOS,ERRbadfid));
504 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
505 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
507 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
513 END_PROFILE(SMBioctl);
517 /****************************************************************************
519 ****************************************************************************/
521 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
527 BOOL bad_path = False;
528 SMB_STRUCT_STAT sbuf;
531 START_PROFILE(SMBchkpth);
533 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
534 if (!NT_STATUS_IS_OK(status)) {
535 END_PROFILE(SMBchkpth);
536 return ERROR_NT(status);
539 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
541 unix_convert(name,conn,0,&bad_path,&sbuf);
543 END_PROFILE(SMBchkpth);
544 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
547 mode = SVAL(inbuf,smb_vwv0);
549 if (check_name(name,conn)) {
550 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
551 if (!(ok = S_ISDIR(sbuf.st_mode))) {
552 END_PROFILE(SMBchkpth);
553 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
558 /* We special case this - as when a Windows machine
559 is parsing a path is steps through the components
560 one at a time - if a component fails it expects
561 ERRbadpath, not ERRbadfile.
563 if(errno == ENOENT) {
565 * Windows returns different error codes if
566 * the parent directory is valid but not the
567 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
568 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
569 * if the path is invalid. This is different from set_bad_path_error()
570 * in the non-NT error case.
572 END_PROFILE(SMBchkpth);
573 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
576 END_PROFILE(SMBchkpth);
577 return(UNIXERROR(ERRDOS,ERRbadpath));
580 outsize = set_message(outbuf,0,0,True);
582 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
584 END_PROFILE(SMBchkpth);
588 /****************************************************************************
590 ****************************************************************************/
592 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
596 SMB_STRUCT_STAT sbuf;
601 BOOL bad_path = False;
605 START_PROFILE(SMBgetatr);
607 p = smb_buf(inbuf) + 1;
608 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
609 if (!NT_STATUS_IS_OK(status)) {
610 END_PROFILE(SMBgetatr);
611 return ERROR_NT(status);
614 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
616 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
617 under WfWg - weird! */
619 mode = aHIDDEN | aDIR;
620 if (!CAN_WRITE(conn))
626 unix_convert(fname,conn,0,&bad_path,&sbuf);
628 END_PROFILE(SMBgetatr);
629 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
631 if (check_name(fname,conn)) {
632 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
633 mode = dos_mode(conn,fname,&sbuf);
635 mtime = sbuf.st_mtime;
640 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
646 END_PROFILE(SMBgetatr);
647 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
650 outsize = set_message(outbuf,10,0,True);
652 SSVAL(outbuf,smb_vwv0,mode);
653 if(lp_dos_filetime_resolution(SNUM(conn)) )
654 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
656 put_dos_date3(outbuf,smb_vwv1,mtime);
657 SIVAL(outbuf,smb_vwv3,(uint32)size);
659 if (Protocol >= PROTOCOL_NT1)
660 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
662 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
664 END_PROFILE(SMBgetatr);
668 /****************************************************************************
670 ****************************************************************************/
672 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
679 SMB_STRUCT_STAT sbuf;
680 BOOL bad_path = False;
684 START_PROFILE(SMBsetatr);
686 p = smb_buf(inbuf) + 1;
687 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
688 if (!NT_STATUS_IS_OK(status)) {
689 END_PROFILE(SMBsetatr);
690 return ERROR_NT(status);
693 unix_convert(fname,conn,0,&bad_path,&sbuf);
695 END_PROFILE(SMBsetatr);
696 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
699 mode = SVAL(inbuf,smb_vwv0);
700 mtime = make_unix_date3(inbuf+smb_vwv1);
702 if (mode != FILE_ATTRIBUTE_NORMAL) {
703 if (VALID_STAT_OF_DIR(sbuf))
708 if (check_name(fname,conn)) {
709 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
716 ok = set_filetime(conn,fname,mtime);
719 END_PROFILE(SMBsetatr);
720 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
723 outsize = set_message(outbuf,0,0,True);
725 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
727 END_PROFILE(SMBsetatr);
731 /****************************************************************************
733 ****************************************************************************/
735 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
738 SMB_BIG_UINT dfree,dsize,bsize;
739 START_PROFILE(SMBdskattr);
741 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
743 outsize = set_message(outbuf,5,0,True);
745 if (Protocol <= PROTOCOL_LANMAN2) {
746 double total_space, free_space;
747 /* we need to scale this to a number that DOS6 can handle. We
748 use floating point so we can handle large drives on systems
749 that don't have 64 bit integers
751 we end up displaying a maximum of 2G to DOS systems
753 total_space = dsize * (double)bsize;
754 free_space = dfree * (double)bsize;
756 dsize = (total_space+63*512) / (64*512);
757 dfree = (free_space+63*512) / (64*512);
759 if (dsize > 0xFFFF) dsize = 0xFFFF;
760 if (dfree > 0xFFFF) dfree = 0xFFFF;
762 SSVAL(outbuf,smb_vwv0,dsize);
763 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
764 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
765 SSVAL(outbuf,smb_vwv3,dfree);
767 SSVAL(outbuf,smb_vwv0,dsize);
768 SSVAL(outbuf,smb_vwv1,bsize/512);
769 SSVAL(outbuf,smb_vwv2,512);
770 SSVAL(outbuf,smb_vwv3,dfree);
773 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
775 END_PROFILE(SMBdskattr);
779 /****************************************************************************
781 Can be called from SMBsearch, SMBffirst or SMBfunique.
782 ****************************************************************************/
784 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
794 unsigned int numentries = 0;
795 unsigned int maxentries = 0;
796 BOOL finished = False;
803 BOOL check_descend = False;
804 BOOL expect_close = False;
805 BOOL can_open = True;
806 BOOL bad_path = False;
808 START_PROFILE(SMBsearch);
810 *mask = *directory = *fname = 0;
812 /* If we were called as SMBffirst then we must expect close. */
813 if(CVAL(inbuf,smb_com) == SMBffirst)
816 outsize = set_message(outbuf,1,3,True);
817 maxentries = SVAL(inbuf,smb_vwv0);
818 dirtype = SVAL(inbuf,smb_vwv1);
819 p = smb_buf(inbuf) + 1;
820 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
821 if (!NT_STATUS_IS_OK(nt_status)) {
822 END_PROFILE(SMBsearch);
823 return ERROR_NT(nt_status);
826 status_len = SVAL(p, 0);
829 /* dirtype &= ~aDIR; */
831 if (status_len == 0) {
832 SMB_STRUCT_STAT sbuf;
835 pstrcpy(directory,path);
837 unix_convert(directory,conn,0,&bad_path,&sbuf);
840 if (!check_name(directory,conn))
843 p = strrchr_m(dir2,'/');
852 p = strrchr_m(directory,'/');
858 if (strlen(directory) == 0)
859 pstrcpy(directory,".");
860 memset((char *)status,'\0',21);
861 SCVAL(status,0,(dirtype & 0x1F));
866 status_dirtype = CVAL(status,0) & 0x1F;
867 if (status_dirtype != (dirtype & 0x1F))
868 dirtype = status_dirtype;
870 conn->dirptr = dptr_fetch(status+12,&dptr_num);
873 string_set(&conn->dirpath,dptr_path(dptr_num));
874 pstrcpy(mask, dptr_wcard(dptr_num));
878 p = smb_buf(outbuf) + 3;
881 if (status_len == 0) {
882 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
885 END_PROFILE(SMBsearch);
886 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
888 END_PROFILE(SMBsearch);
889 return ERROR_DOS(ERRDOS,ERRnofids);
891 dptr_set_wcard(dptr_num, strdup(mask));
892 dptr_set_attr(dptr_num, dirtype);
894 dirtype = dptr_attr(dptr_num);
897 DEBUG(4,("dptr_num is %d\n",dptr_num));
900 if ((dirtype&0x1F) == aVOLID) {
902 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
903 dptr_fill(p+12,dptr_num);
904 if (dptr_zero(p+12) && (status_len==0))
908 p += DIR_STRUCT_SIZE;
911 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
913 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
914 conn->dirpath,lp_dontdescend(SNUM(conn))));
915 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
916 check_descend = True;
918 for (i=numentries;(i<maxentries) && !finished;i++) {
919 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
922 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
923 dptr_fill(p+12,dptr_num);
926 p += DIR_STRUCT_SIZE;
935 /* If we were called as SMBffirst with smb_search_id == NULL
936 and no entries were found then return error and close dirptr
939 if(ok && expect_close && numentries == 0 && status_len == 0) {
940 if (Protocol < PROTOCOL_NT1) {
941 SCVAL(outbuf,smb_rcls,ERRDOS);
942 SSVAL(outbuf,smb_err,ERRnofiles);
944 /* Also close the dptr - we know it's gone */
945 dptr_close(&dptr_num);
946 } else if (numentries == 0 || !ok) {
947 if (Protocol < PROTOCOL_NT1) {
948 SCVAL(outbuf,smb_rcls,ERRDOS);
949 SSVAL(outbuf,smb_err,ERRnofiles);
951 dptr_close(&dptr_num);
954 /* If we were called as SMBfunique, then we can close the dirptr now ! */
955 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
956 dptr_close(&dptr_num);
958 SSVAL(outbuf,smb_vwv0,numentries);
959 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
960 SCVAL(smb_buf(outbuf),0,5);
961 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
963 if (Protocol >= PROTOCOL_NT1)
964 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
966 outsize += DIR_STRUCT_SIZE*numentries;
967 smb_setlen(outbuf,outsize - 4);
969 if ((! *directory) && dptr_path(dptr_num))
970 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
972 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
973 smb_fn_name(CVAL(inbuf,smb_com)),
974 mask, directory, dirtype, numentries, maxentries ) );
976 END_PROFILE(SMBsearch);
980 /****************************************************************************
981 Reply to a fclose (stop directory search).
982 ****************************************************************************/
984 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
994 START_PROFILE(SMBfclose);
996 outsize = set_message(outbuf,1,0,True);
997 p = smb_buf(inbuf) + 1;
998 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
999 if (!NT_STATUS_IS_OK(err)) {
1000 END_PROFILE(SMBfclose);
1001 return ERROR_NT(err);
1004 status_len = SVAL(p,0);
1007 if (status_len == 0) {
1008 END_PROFILE(SMBfclose);
1009 return ERROR_DOS(ERRSRV,ERRsrverror);
1012 memcpy(status,p,21);
1014 if(dptr_fetch(status+12,&dptr_num)) {
1015 /* Close the dptr - we know it's gone */
1016 dptr_close(&dptr_num);
1019 SSVAL(outbuf,smb_vwv0,0);
1021 DEBUG(3,("search close\n"));
1023 END_PROFILE(SMBfclose);
1027 /****************************************************************************
1029 ****************************************************************************/
1031 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1040 SMB_STRUCT_STAT sbuf;
1041 BOOL bad_path = False;
1043 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1044 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1046 START_PROFILE(SMBopen);
1048 share_mode = SVAL(inbuf,smb_vwv0);
1050 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 END_PROFILE(SMBopen);
1053 return ERROR_NT(status);
1056 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1058 unix_convert(fname,conn,0,&bad_path,&sbuf);
1060 END_PROFILE(SMBopen);
1061 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1064 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1065 (uint32)dos_attr, oplock_request,&rmode,NULL);
1068 END_PROFILE(SMBopen);
1069 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1070 /* We have re-scheduled this call. */
1071 clear_cached_errors();
1074 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1077 size = sbuf.st_size;
1078 fmode = dos_mode(conn,fname,&sbuf);
1079 mtime = sbuf.st_mtime;
1082 DEBUG(3,("attempt to open a directory %s\n",fname));
1083 close_file(fsp,False);
1084 END_PROFILE(SMBopen);
1085 return ERROR_DOS(ERRDOS,ERRnoaccess);
1088 outsize = set_message(outbuf,7,0,True);
1089 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1090 SSVAL(outbuf,smb_vwv1,fmode);
1091 if(lp_dos_filetime_resolution(SNUM(conn)) )
1092 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1094 put_dos_date3(outbuf,smb_vwv2,mtime);
1095 SIVAL(outbuf,smb_vwv4,(uint32)size);
1096 SSVAL(outbuf,smb_vwv6,rmode);
1098 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1099 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1101 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1102 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1103 END_PROFILE(SMBopen);
1107 /****************************************************************************
1108 Reply to an open and X.
1109 ****************************************************************************/
1111 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1114 int smb_mode = SVAL(inbuf,smb_vwv3);
1115 int smb_attr = SVAL(inbuf,smb_vwv5);
1116 /* Breakout the oplock request bits so we can set the
1117 reply bits separately. */
1118 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1119 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1120 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1122 int open_flags = SVAL(inbuf,smb_vwv2);
1123 int smb_sattr = SVAL(inbuf,smb_vwv4);
1124 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1126 int smb_ofun = SVAL(inbuf,smb_vwv8);
1128 int fmode=0,mtime=0,rmode=0;
1129 SMB_STRUCT_STAT sbuf;
1131 BOOL bad_path = False;
1134 START_PROFILE(SMBopenX);
1136 /* If it's an IPC, pass off the pipe handler. */
1138 if (lp_nt_pipe_support()) {
1139 END_PROFILE(SMBopenX);
1140 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1142 END_PROFILE(SMBopenX);
1143 return ERROR_DOS(ERRSRV,ERRaccess);
1147 /* XXXX we need to handle passed times, sattr and flags */
1148 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 END_PROFILE(SMBopenX);
1151 return ERROR_NT(status);
1154 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1156 unix_convert(fname,conn,0,&bad_path,&sbuf);
1158 END_PROFILE(SMBopenX);
1159 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1162 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1163 oplock_request, &rmode,&smb_action);
1166 END_PROFILE(SMBopenX);
1167 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1168 /* We have re-scheduled this call. */
1169 clear_cached_errors();
1172 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1175 size = sbuf.st_size;
1176 fmode = dos_mode(conn,fname,&sbuf);
1177 mtime = sbuf.st_mtime;
1179 close_file(fsp,False);
1180 END_PROFILE(SMBopenX);
1181 return ERROR_DOS(ERRDOS,ERRnoaccess);
1184 /* If the caller set the extended oplock request bit
1185 and we granted one (by whatever means) - set the
1186 correct bit for extended oplock reply.
1189 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1190 smb_action |= EXTENDED_OPLOCK_GRANTED;
1192 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1193 smb_action |= EXTENDED_OPLOCK_GRANTED;
1195 /* If the caller set the core oplock request bit
1196 and we granted one (by whatever means) - set the
1197 correct bit for core oplock reply.
1200 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1201 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1203 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1204 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1206 set_message(outbuf,15,0,True);
1207 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1208 SSVAL(outbuf,smb_vwv3,fmode);
1209 if(lp_dos_filetime_resolution(SNUM(conn)) )
1210 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1212 put_dos_date3(outbuf,smb_vwv4,mtime);
1213 SIVAL(outbuf,smb_vwv6,(uint32)size);
1214 SSVAL(outbuf,smb_vwv8,rmode);
1215 SSVAL(outbuf,smb_vwv11,smb_action);
1217 END_PROFILE(SMBopenX);
1218 return chain_reply(inbuf,outbuf,length,bufsize);
1221 /****************************************************************************
1222 Reply to a SMBulogoffX.
1223 ****************************************************************************/
1225 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1227 uint16 vuid = SVAL(inbuf,smb_uid);
1228 user_struct *vuser = get_valid_user_struct(vuid);
1229 START_PROFILE(SMBulogoffX);
1232 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1234 /* in user level security we are supposed to close any files
1235 open by this user */
1236 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1237 file_close_user(vuid);
1239 invalidate_vuid(vuid);
1241 set_message(outbuf,2,0,True);
1243 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1245 END_PROFILE(SMBulogoffX);
1246 return chain_reply(inbuf,outbuf,length,bufsize);
1249 /****************************************************************************
1250 Reply to a mknew or a create.
1251 ****************************************************************************/
1253 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1260 BOOL bad_path = False;
1262 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1263 SMB_STRUCT_STAT sbuf;
1265 START_PROFILE(SMBcreate);
1267 com = SVAL(inbuf,smb_com);
1269 createmode = SVAL(inbuf,smb_vwv0);
1270 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 END_PROFILE(SMBcreate);
1273 return ERROR_NT(status);
1276 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1278 unix_convert(fname,conn,0,&bad_path,&sbuf);
1280 END_PROFILE(SMBcreate);
1281 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1284 if (createmode & aVOLID)
1285 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1287 if(com == SMBmknew) {
1288 /* We should fail if file exists. */
1289 ofun = FILE_CREATE_IF_NOT_EXIST;
1291 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1292 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1295 /* Open file in dos compatibility share mode. */
1296 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1297 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1300 END_PROFILE(SMBcreate);
1301 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1302 /* We have re-scheduled this call. */
1303 clear_cached_errors();
1306 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1309 outsize = set_message(outbuf,1,0,True);
1310 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1312 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1313 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1315 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1316 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1318 DEBUG( 2, ( "new file %s\n", fname ) );
1319 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1321 END_PROFILE(SMBcreate);
1325 /****************************************************************************
1326 Reply to a create temporary file.
1327 ****************************************************************************/
1329 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1334 BOOL bad_path = False;
1336 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1338 SMB_STRUCT_STAT sbuf;
1341 unsigned int namelen;
1343 START_PROFILE(SMBctemp);
1345 createattr = SVAL(inbuf,smb_vwv0);
1346 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 END_PROFILE(SMBctemp);
1349 return ERROR_NT(status);
1352 pstrcat(fname,"/TMXXXXXX");
1354 pstrcat(fname,"TMXXXXXX");
1357 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1359 unix_convert(fname,conn,0,&bad_path,&sbuf);
1361 END_PROFILE(SMBctemp);
1362 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1365 tmpfd = smb_mkstemp(fname);
1367 END_PROFILE(SMBctemp);
1368 return(UNIXERROR(ERRDOS,ERRnoaccess));
1371 SMB_VFS_STAT(conn,fname,&sbuf);
1373 /* Open file in dos compatibility share mode. */
1374 /* We should fail if file does not exist. */
1375 fsp = open_file_shared(conn,fname,&sbuf,
1376 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1377 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1378 (uint32)createattr, oplock_request, NULL, NULL);
1380 /* close fd from smb_mkstemp() */
1384 END_PROFILE(SMBctemp);
1385 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1386 /* We have re-scheduled this call. */
1387 clear_cached_errors();
1390 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1393 outsize = set_message(outbuf,1,0,True);
1394 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1396 /* the returned filename is relative to the directory */
1397 s = strrchr_m(fname, '/');
1403 p = smb_buf(outbuf);
1405 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1406 thing in the byte section. JRA */
1407 SSVALS(p, 0, -1); /* what is this? not in spec */
1409 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1411 outsize = set_message_end(outbuf, p);
1413 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1414 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1416 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1417 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1419 DEBUG( 2, ( "created temp file %s\n", fname ) );
1420 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1421 fname, fsp->fd, sbuf.st_mode ) );
1423 END_PROFILE(SMBctemp);
1427 /*******************************************************************
1428 Check if a user is allowed to rename a file.
1429 ********************************************************************/
1431 static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
1438 if (!CAN_WRITE(conn))
1439 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1441 fmode = dos_mode(conn,fname,pst);
1442 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1443 return NT_STATUS_NO_SUCH_FILE;
1445 if (S_ISDIR(pst->st_mode))
1446 return NT_STATUS_OK;
1448 /* We need a better way to return NT status codes from open... */
1452 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1453 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1456 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1457 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1458 ret = NT_STATUS_SHARING_VIOLATION;
1461 unix_ERR_ntstatus = NT_STATUS_OK;
1464 close_file(fsp,False);
1465 return NT_STATUS_OK;
1468 /*******************************************************************
1469 Check if a user is allowed to delete a file.
1470 ********************************************************************/
1472 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1474 SMB_STRUCT_STAT sbuf;
1480 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1483 if (!CAN_WRITE(conn))
1484 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1486 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1487 if(errno == ENOENT) {
1489 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1491 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1493 return map_nt_error_from_unix(errno);
1496 fmode = dos_mode(conn,fname,&sbuf);
1498 /* Can't delete a directory. */
1500 return NT_STATUS_FILE_IS_A_DIRECTORY;
1502 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1503 return NT_STATUS_OBJECT_NAME_INVALID;
1504 #endif /* JRATEST */
1506 if (!lp_delete_readonly(SNUM(conn))) {
1508 return NT_STATUS_CANNOT_DELETE;
1510 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1511 return NT_STATUS_NO_SUCH_FILE;
1513 /* We need a better way to return NT status codes from open... */
1517 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1518 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1521 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1522 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1523 ret = unix_ERR_ntstatus;
1524 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1525 ret = NT_STATUS_SHARING_VIOLATION;
1528 unix_ERR_ntstatus = NT_STATUS_OK;
1531 close_file(fsp,False);
1532 return NT_STATUS_OK;
1535 /****************************************************************************
1536 The guts of the unlink command, split out so it may be called by the NT SMB
1538 ****************************************************************************/
1540 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1546 NTSTATUS error = NT_STATUS_OK;
1548 BOOL bad_path = False;
1550 SMB_STRUCT_STAT sbuf;
1552 *directory = *mask = 0;
1554 /* We must check for wildcards in the name given
1555 * directly by the client - before any unmangling.
1556 * This prevents an unmangling of a UNIX name containing
1557 * a DOS wildcard like '*' or '?' from unmangling into
1558 * a wildcard delete which was not intended.
1559 * FIX for #226. JRA.
1562 has_wild = ms_has_wild(name);
1564 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1566 p = strrchr_m(name,'/');
1568 pstrcpy(directory,".");
1572 pstrcpy(directory,name);
1577 * We should only check the mangled cache
1578 * here if unix_convert failed. This means
1579 * that the path in 'mask' doesn't exist
1580 * on the file system and so we need to look
1581 * for a possible mangle. This patch from
1582 * Tine Smukavec <valentin.smukavec@hermes.si>.
1585 if (!rc && mangle_is_mangled(mask))
1586 mangle_check_cache( mask, sizeof(pstring)-1 );
1589 pstrcat(directory,"/");
1590 pstrcat(directory,mask);
1591 error = can_delete(directory,conn,dirtype,bad_path);
1592 if (!NT_STATUS_IS_OK(error))
1595 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1599 void *dirptr = NULL;
1602 if (check_name(directory,conn))
1603 dirptr = OpenDir(conn, directory, True);
1605 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1606 the pattern matches against the long name, otherwise the short name
1607 We don't implement this yet XXXX
1611 error = NT_STATUS_NO_SUCH_FILE;
1613 if (strequal(mask,"????????.???"))
1616 while ((dname = ReadDirName(dirptr))) {
1618 BOOL sys_direntry = False;
1619 pstrcpy(fname,dname);
1621 /* Quick check for "." and ".." */
1622 if (fname[0] == '.') {
1623 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1624 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1625 sys_direntry = True;
1632 if(!mask_match(fname, mask, conn->case_sensitive))
1636 error = NT_STATUS_OBJECT_NAME_INVALID;
1637 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1642 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1643 error = can_delete(fname,conn,dirtype,bad_path);
1644 if (!NT_STATUS_IS_OK(error)) {
1647 if (SMB_VFS_UNLINK(conn,fname) == 0)
1649 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1655 if (count == 0 && NT_STATUS_IS_OK(error)) {
1656 error = map_nt_error_from_unix(errno);
1662 /****************************************************************************
1664 ****************************************************************************/
1666 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1673 START_PROFILE(SMBunlink);
1675 dirtype = SVAL(inbuf,smb_vwv0);
1677 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1678 if (!NT_STATUS_IS_OK(status)) {
1679 END_PROFILE(SMBunlink);
1680 return ERROR_NT(status);
1683 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1685 DEBUG(3,("reply_unlink : %s\n",name));
1687 status = unlink_internals(conn, dirtype, name);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1690 /* We have re-scheduled this call. */
1691 clear_cached_errors();
1694 return ERROR_NT(status);
1698 * Win2k needs a changenotify request response before it will
1699 * update after a rename..
1701 process_pending_change_notify_queue((time_t)0);
1703 outsize = set_message(outbuf,0,0,True);
1705 END_PROFILE(SMBunlink);
1709 /****************************************************************************
1711 ****************************************************************************/
1713 void fail_readraw(void)
1716 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1718 exit_server(errstr);
1721 /****************************************************************************
1722 Use sendfile in readbraw.
1723 ****************************************************************************/
1725 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1726 ssize_t mincount, char *outbuf)
1730 #if defined(WITH_SENDFILE)
1732 * We can only use sendfile on a non-chained packet
1733 * but we can use on a non-oplocked file. tridge proved this
1734 * on a train in Germany :-). JRA.
1735 * reply_readbraw has already checked the length.
1738 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1741 _smb_setlen(outbuf,nread);
1742 header.data = outbuf;
1746 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1748 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1749 * return ENOSYS then pretend we just got a normal read.
1751 if (errno == ENOSYS) {
1752 set_use_sendfile(SNUM(conn), False);
1756 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1757 fsp->fsp_name, strerror(errno) ));
1758 exit_server("send_file_readbraw sendfile failed");
1767 ret = read_file(fsp,outbuf+4,startpos,nread);
1768 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1777 _smb_setlen(outbuf,ret);
1778 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1782 /****************************************************************************
1783 Reply to a readbraw (core+ protocol).
1784 ****************************************************************************/
1786 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1788 extern struct current_user current_user;
1789 ssize_t maxcount,mincount;
1792 char *header = outbuf;
1794 START_PROFILE(SMBreadbraw);
1796 if (srv_is_signing_active()) {
1797 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1801 * Special check if an oplock break has been issued
1802 * and the readraw request croses on the wire, we must
1803 * return a zero length response here.
1806 if(global_oplock_break) {
1807 _smb_setlen(header,0);
1808 if (write_data(smbd_server_fd(),header,4) != 4)
1810 DEBUG(5,("readbraw - oplock break finished\n"));
1811 END_PROFILE(SMBreadbraw);
1815 fsp = file_fsp(inbuf,smb_vwv0);
1817 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1819 * fsp could be NULL here so use the value from the packet. JRA.
1821 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1822 _smb_setlen(header,0);
1823 if (write_data(smbd_server_fd(),header,4) != 4)
1825 END_PROFILE(SMBreadbraw);
1829 CHECK_FSP(fsp,conn);
1831 flush_write_cache(fsp, READRAW_FLUSH);
1833 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1834 if(CVAL(inbuf,smb_wct) == 10) {
1836 * This is a large offset (64 bit) read.
1838 #ifdef LARGE_SMB_OFF_T
1840 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1842 #else /* !LARGE_SMB_OFF_T */
1845 * Ensure we haven't been sent a >32 bit offset.
1848 if(IVAL(inbuf,smb_vwv8) != 0) {
1849 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1850 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1851 _smb_setlen(header,0);
1852 if (write_data(smbd_server_fd(),header,4) != 4)
1854 END_PROFILE(SMBreadbraw);
1858 #endif /* LARGE_SMB_OFF_T */
1861 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1862 _smb_setlen(header,0);
1863 if (write_data(smbd_server_fd(),header,4) != 4)
1865 END_PROFILE(SMBreadbraw);
1869 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1870 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1872 /* ensure we don't overrun the packet size */
1873 maxcount = MIN(65535,maxcount);
1875 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1876 SMB_OFF_T size = fsp->size;
1877 SMB_OFF_T sizeneeded = startpos + maxcount;
1879 if (size < sizeneeded) {
1881 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1883 if (!fsp->can_write)
1887 if (startpos >= size)
1890 nread = MIN(maxcount,(size - startpos));
1893 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1894 if (nread < mincount)
1898 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1899 (int)maxcount, (int)mincount, (int)nread ) );
1901 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1903 DEBUG(5,("readbraw finished\n"));
1904 END_PROFILE(SMBreadbraw);
1908 /****************************************************************************
1909 Reply to a lockread (core+ protocol).
1910 ****************************************************************************/
1912 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1920 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1921 BOOL my_lock_ctx = False;
1922 START_PROFILE(SMBlockread);
1924 CHECK_FSP(fsp,conn);
1927 release_level_2_oplocks_on_change(fsp);
1929 numtoread = SVAL(inbuf,smb_vwv1);
1930 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1932 outsize = set_message(outbuf,5,3,True);
1933 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1934 data = smb_buf(outbuf) + 3;
1937 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1938 * protocol request that predates the read/write lock concept.
1939 * Thus instead of asking for a read lock here we need to ask
1940 * for a write lock. JRA.
1941 * Note that the requested lock size is unaffected by max_recv.
1944 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1945 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1947 if (NT_STATUS_V(status)) {
1950 * We used to make lockread a blocking lock. It turns out
1951 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1955 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1957 * A blocking lock was requested. Package up
1958 * this smb into a queued request and push it
1959 * onto the blocking lock queue.
1961 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1962 (SMB_BIG_UINT)numtoread)) {
1963 END_PROFILE(SMBlockread);
1968 END_PROFILE(SMBlockread);
1969 return ERROR_NT(status);
1973 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1976 if (numtoread > max_recv) {
1977 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1978 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1979 (unsigned int)numtoread, (unsigned int)max_recv ));
1980 numtoread = MIN(numtoread,max_recv);
1982 nread = read_file(fsp,data,startpos,numtoread);
1985 END_PROFILE(SMBlockread);
1986 return(UNIXERROR(ERRDOS,ERRnoaccess));
1990 SSVAL(outbuf,smb_vwv0,nread);
1991 SSVAL(outbuf,smb_vwv5,nread+3);
1992 SSVAL(smb_buf(outbuf),1,nread);
1994 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1995 fsp->fnum, (int)numtoread, (int)nread));
1997 END_PROFILE(SMBlockread);
2001 /****************************************************************************
2003 ****************************************************************************/
2005 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2012 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2013 START_PROFILE(SMBread);
2015 CHECK_FSP(fsp,conn);
2018 numtoread = SVAL(inbuf,smb_vwv1);
2019 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2021 outsize = set_message(outbuf,5,3,True);
2022 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2024 * The requested read size cannot be greater than max_recv. JRA.
2026 if (numtoread > max_recv) {
2027 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2028 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2029 (unsigned int)numtoread, (unsigned int)max_recv ));
2030 numtoread = MIN(numtoread,max_recv);
2033 data = smb_buf(outbuf) + 3;
2035 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2036 END_PROFILE(SMBread);
2037 return ERROR_DOS(ERRDOS,ERRlock);
2041 nread = read_file(fsp,data,startpos,numtoread);
2044 END_PROFILE(SMBread);
2045 return(UNIXERROR(ERRDOS,ERRnoaccess));
2049 SSVAL(outbuf,smb_vwv0,nread);
2050 SSVAL(outbuf,smb_vwv5,nread+3);
2051 SCVAL(smb_buf(outbuf),0,1);
2052 SSVAL(smb_buf(outbuf),1,nread);
2054 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2055 fsp->fnum, (int)numtoread, (int)nread ) );
2057 END_PROFILE(SMBread);
2061 /****************************************************************************
2062 Reply to a read and X - possibly using sendfile.
2063 ****************************************************************************/
2065 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
2066 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2069 char *data = smb_buf(outbuf);
2071 #if defined(WITH_SENDFILE)
2073 * We can only use sendfile on a non-chained packet
2074 * but we can use on a non-oplocked file. tridge proved this
2075 * on a train in Germany :-). JRA.
2078 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2079 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2080 SMB_STRUCT_STAT sbuf;
2083 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2084 return(UNIXERROR(ERRDOS,ERRnoaccess));
2086 if (startpos > sbuf.st_size)
2089 if (smb_maxcnt > (sbuf.st_size - startpos))
2090 smb_maxcnt = (sbuf.st_size - startpos);
2092 if (smb_maxcnt == 0)
2096 * Set up the packet header before send. We
2097 * assume here the sendfile will work (get the
2098 * correct amount of data).
2101 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2102 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2103 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2104 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2105 SCVAL(outbuf,smb_vwv0,0xFF);
2106 set_message(outbuf,12,smb_maxcnt,False);
2107 header.data = outbuf;
2108 header.length = data - outbuf;
2111 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2113 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2114 * return ENOSYS then pretend we just got a normal read.
2116 if (errno == ENOSYS) {
2117 set_use_sendfile(SNUM(conn), False);
2121 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2122 fsp->fsp_name, strerror(errno) ));
2123 exit_server("send_file_readX sendfile failed");
2126 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2127 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2135 nread = read_file(fsp,data,startpos,smb_maxcnt);
2138 END_PROFILE(SMBreadX);
2139 return(UNIXERROR(ERRDOS,ERRnoaccess));
2142 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2143 SSVAL(outbuf,smb_vwv5,nread);
2144 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2145 SSVAL(smb_buf(outbuf),-2,nread);
2147 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2148 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2153 /****************************************************************************
2154 Reply to a read and X.
2155 ****************************************************************************/
2157 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2159 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2160 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2162 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2164 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2167 START_PROFILE(SMBreadX);
2169 /* If it's an IPC, pass off the pipe handler. */
2171 END_PROFILE(SMBreadX);
2172 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2175 CHECK_FSP(fsp,conn);
2178 set_message(outbuf,12,0,True);
2180 if(CVAL(inbuf,smb_wct) == 12) {
2181 #ifdef LARGE_SMB_OFF_T
2183 * This is a large offset (64 bit) read.
2185 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2187 #else /* !LARGE_SMB_OFF_T */
2190 * Ensure we haven't been sent a >32 bit offset.
2193 if(IVAL(inbuf,smb_vwv10) != 0) {
2194 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2195 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2196 END_PROFILE(SMBreadX);
2197 return ERROR_DOS(ERRDOS,ERRbadaccess);
2200 #endif /* LARGE_SMB_OFF_T */
2204 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2205 END_PROFILE(SMBreadX);
2206 return ERROR_DOS(ERRDOS,ERRlock);
2209 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2211 nread = chain_reply(inbuf,outbuf,length,bufsize);
2213 END_PROFILE(SMBreadX);
2217 /****************************************************************************
2218 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2219 ****************************************************************************/
2221 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2224 ssize_t total_written=0;
2225 size_t numtowrite=0;
2230 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2232 START_PROFILE(SMBwritebraw);
2234 if (srv_is_signing_active()) {
2235 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2238 CHECK_FSP(fsp,conn);
2241 tcount = IVAL(inbuf,smb_vwv1);
2242 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2243 write_through = BITSETW(inbuf+smb_vwv7,0);
2245 /* We have to deal with slightly different formats depending
2246 on whether we are using the core+ or lanman1.0 protocol */
2248 if(Protocol <= PROTOCOL_COREPLUS) {
2249 numtowrite = SVAL(smb_buf(inbuf),-2);
2250 data = smb_buf(inbuf);
2252 numtowrite = SVAL(inbuf,smb_vwv10);
2253 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2256 /* force the error type */
2257 SCVAL(inbuf,smb_com,SMBwritec);
2258 SCVAL(outbuf,smb_com,SMBwritec);
2260 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2261 END_PROFILE(SMBwritebraw);
2262 return(ERROR_DOS(ERRDOS,ERRlock));
2266 nwritten = write_file(fsp,data,startpos,numtowrite);
2268 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2269 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2271 if (nwritten < (ssize_t)numtowrite) {
2272 END_PROFILE(SMBwritebraw);
2273 return(UNIXERROR(ERRHRD,ERRdiskfull));
2276 total_written = nwritten;
2278 /* Return a message to the redirector to tell it to send more bytes */
2279 SCVAL(outbuf,smb_com,SMBwritebraw);
2280 SSVALS(outbuf,smb_vwv0,-1);
2281 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2282 if (!send_smb(smbd_server_fd(),outbuf))
2283 exit_server("reply_writebraw: send_smb failed.");
2285 /* Now read the raw data into the buffer and write it */
2286 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2287 exit_server("secondary writebraw failed");
2290 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2291 numtowrite = smb_len(inbuf);
2293 /* Set up outbuf to return the correct return */
2294 outsize = set_message(outbuf,1,0,True);
2295 SCVAL(outbuf,smb_com,SMBwritec);
2296 SSVAL(outbuf,smb_vwv0,total_written);
2298 if (numtowrite != 0) {
2300 if (numtowrite > BUFFER_SIZE) {
2301 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2302 (unsigned int)numtowrite ));
2303 exit_server("secondary writebraw failed");
2306 if (tcount > nwritten+numtowrite) {
2307 DEBUG(3,("Client overestimated the write %d %d %d\n",
2308 (int)tcount,(int)nwritten,(int)numtowrite));
2311 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2312 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2314 exit_server("secondary writebraw failed");
2317 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2319 if (nwritten < (ssize_t)numtowrite) {
2320 SCVAL(outbuf,smb_rcls,ERRHRD);
2321 SSVAL(outbuf,smb_err,ERRdiskfull);
2325 total_written += nwritten;
2328 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2329 sync_file(conn,fsp);
2331 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2332 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2334 /* we won't return a status if write through is not selected - this follows what WfWg does */
2335 END_PROFILE(SMBwritebraw);
2336 if (!write_through && total_written==tcount) {
2338 #if RABBIT_PELLET_FIX
2340 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2341 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2343 if (!send_keepalive(smbd_server_fd()))
2344 exit_server("reply_writebraw: send of keepalive failed");
2352 /****************************************************************************
2353 Reply to a writeunlock (core+).
2354 ****************************************************************************/
2356 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2357 int size, int dum_buffsize)
2359 ssize_t nwritten = -1;
2363 NTSTATUS status = NT_STATUS_OK;
2364 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2366 START_PROFILE(SMBwriteunlock);
2368 CHECK_FSP(fsp,conn);
2371 numtowrite = SVAL(inbuf,smb_vwv1);
2372 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2373 data = smb_buf(inbuf) + 3;
2375 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2376 WRITE_LOCK,False)) {
2377 END_PROFILE(SMBwriteunlock);
2378 return ERROR_DOS(ERRDOS,ERRlock);
2381 /* The special X/Open SMB protocol handling of
2382 zero length writes is *NOT* done for
2387 nwritten = write_file(fsp,data,startpos,numtowrite);
2389 if (lp_syncalways(SNUM(conn)))
2390 sync_file(conn,fsp);
2392 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2393 END_PROFILE(SMBwriteunlock);
2394 return(UNIXERROR(ERRHRD,ERRdiskfull));
2398 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2399 (SMB_BIG_UINT)startpos);
2400 if (NT_STATUS_V(status)) {
2401 END_PROFILE(SMBwriteunlock);
2402 return ERROR_NT(status);
2406 outsize = set_message(outbuf,1,0,True);
2408 SSVAL(outbuf,smb_vwv0,nwritten);
2410 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2411 fsp->fnum, (int)numtowrite, (int)nwritten));
2413 END_PROFILE(SMBwriteunlock);
2417 /****************************************************************************
2419 ****************************************************************************/
2421 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2424 ssize_t nwritten = -1;
2427 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2429 START_PROFILE(SMBwrite);
2431 /* If it's an IPC, pass off the pipe handler. */
2433 END_PROFILE(SMBwrite);
2434 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2437 CHECK_FSP(fsp,conn);
2440 numtowrite = SVAL(inbuf,smb_vwv1);
2441 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2442 data = smb_buf(inbuf) + 3;
2444 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2445 END_PROFILE(SMBwrite);
2446 return ERROR_DOS(ERRDOS,ERRlock);
2450 * X/Open SMB protocol says that if smb_vwv1 is
2451 * zero then the file size should be extended or
2452 * truncated to the size given in smb_vwv[2-3].
2455 if(numtowrite == 0) {
2457 * This is actually an allocate call, and set EOF. JRA.
2459 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2461 END_PROFILE(SMBwrite);
2462 return ERROR_NT(NT_STATUS_DISK_FULL);
2464 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2466 END_PROFILE(SMBwrite);
2467 return ERROR_NT(NT_STATUS_DISK_FULL);
2470 nwritten = write_file(fsp,data,startpos,numtowrite);
2472 if (lp_syncalways(SNUM(conn)))
2473 sync_file(conn,fsp);
2475 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2476 END_PROFILE(SMBwrite);
2477 return(UNIXERROR(ERRHRD,ERRdiskfull));
2480 outsize = set_message(outbuf,1,0,True);
2482 SSVAL(outbuf,smb_vwv0,nwritten);
2484 if (nwritten < (ssize_t)numtowrite) {
2485 SCVAL(outbuf,smb_rcls,ERRHRD);
2486 SSVAL(outbuf,smb_err,ERRdiskfull);
2489 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2491 END_PROFILE(SMBwrite);
2495 /****************************************************************************
2496 Reply to a write and X.
2497 ****************************************************************************/
2499 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2501 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2502 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2503 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2504 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2505 ssize_t nwritten = -1;
2506 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2507 unsigned int smblen = smb_len(inbuf);
2509 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2510 START_PROFILE(SMBwriteX);
2512 /* If it's an IPC, pass off the pipe handler. */
2514 END_PROFILE(SMBwriteX);
2515 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2518 CHECK_FSP(fsp,conn);
2521 /* Deal with possible LARGE_WRITEX */
2523 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2525 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2526 END_PROFILE(SMBwriteX);
2527 return ERROR_DOS(ERRDOS,ERRbadmem);
2530 data = smb_base(inbuf) + smb_doff;
2532 if(CVAL(inbuf,smb_wct) == 14) {
2533 #ifdef LARGE_SMB_OFF_T
2535 * This is a large offset (64 bit) write.
2537 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2539 #else /* !LARGE_SMB_OFF_T */
2542 * Ensure we haven't been sent a >32 bit offset.
2545 if(IVAL(inbuf,smb_vwv12) != 0) {
2546 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2547 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2548 END_PROFILE(SMBwriteX);
2549 return ERROR_DOS(ERRDOS,ERRbadaccess);
2552 #endif /* LARGE_SMB_OFF_T */
2555 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2556 END_PROFILE(SMBwriteX);
2557 return ERROR_DOS(ERRDOS,ERRlock);
2560 /* X/Open SMB protocol says that, unlike SMBwrite
2561 if the length is zero then NO truncation is
2562 done, just a write of zero. To truncate a file,
2568 nwritten = write_file(fsp,data,startpos,numtowrite);
2570 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2571 END_PROFILE(SMBwriteX);
2572 return(UNIXERROR(ERRHRD,ERRdiskfull));
2575 set_message(outbuf,6,0,True);
2577 SSVAL(outbuf,smb_vwv2,nwritten);
2579 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2581 if (nwritten < (ssize_t)numtowrite) {
2582 SCVAL(outbuf,smb_rcls,ERRHRD);
2583 SSVAL(outbuf,smb_err,ERRdiskfull);
2586 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2587 fsp->fnum, (int)numtowrite, (int)nwritten));
2589 if (lp_syncalways(SNUM(conn)) || write_through)
2590 sync_file(conn,fsp);
2592 END_PROFILE(SMBwriteX);
2593 return chain_reply(inbuf,outbuf,length,bufsize);
2596 /****************************************************************************
2598 ****************************************************************************/
2600 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2606 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2607 START_PROFILE(SMBlseek);
2609 CHECK_FSP(fsp,conn);
2611 flush_write_cache(fsp, SEEK_FLUSH);
2613 mode = SVAL(inbuf,smb_vwv1) & 3;
2614 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2615 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2624 res = fsp->pos + startpos;
2635 if (umode == SEEK_END) {
2636 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2637 if(errno == EINVAL) {
2638 SMB_OFF_T current_pos = startpos;
2639 SMB_STRUCT_STAT sbuf;
2641 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2642 END_PROFILE(SMBlseek);
2643 return(UNIXERROR(ERRDOS,ERRnoaccess));
2646 current_pos += sbuf.st_size;
2648 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2653 END_PROFILE(SMBlseek);
2654 return(UNIXERROR(ERRDOS,ERRnoaccess));
2660 outsize = set_message(outbuf,2,0,True);
2661 SIVAL(outbuf,smb_vwv0,res);
2663 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2664 fsp->fnum, (double)startpos, (double)res, mode));
2666 END_PROFILE(SMBlseek);
2670 /****************************************************************************
2672 ****************************************************************************/
2674 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2676 int outsize = set_message(outbuf,0,0,True);
2677 uint16 fnum = SVAL(inbuf,smb_vwv0);
2678 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2679 START_PROFILE(SMBflush);
2682 CHECK_FSP(fsp,conn);
2685 file_sync_all(conn);
2687 sync_file(conn,fsp);
2690 DEBUG(3,("flush\n"));
2691 END_PROFILE(SMBflush);
2695 /****************************************************************************
2697 ****************************************************************************/
2699 int reply_exit(connection_struct *conn,
2700 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2703 START_PROFILE(SMBexit);
2705 file_close_pid(SVAL(inbuf,smb_pid));
2707 outsize = set_message(outbuf,0,0,True);
2709 DEBUG(3,("exit\n"));
2711 END_PROFILE(SMBexit);
2715 /****************************************************************************
2716 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2717 ****************************************************************************/
2719 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2722 extern struct current_user current_user;
2725 int32 eclass = 0, err = 0;
2726 files_struct *fsp = NULL;
2727 START_PROFILE(SMBclose);
2729 outsize = set_message(outbuf,0,0,True);
2731 /* If it's an IPC, pass off to the pipe handler. */
2733 END_PROFILE(SMBclose);
2734 return reply_pipe_close(conn, inbuf,outbuf);
2737 fsp = file_fsp(inbuf,smb_vwv0);
2740 * We can only use CHECK_FSP if we know it's not a directory.
2743 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2744 END_PROFILE(SMBclose);
2745 return ERROR_DOS(ERRDOS,ERRbadfid);
2748 if(fsp->is_directory) {
2750 * Special case - close NT SMB directory handle.
2752 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2753 close_file(fsp,True);
2756 * Close ordinary file.
2761 /* Save the name for time set in close. */
2762 pstrcpy( file_name, fsp->fsp_name);
2764 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2766 conn->num_files_open));
2769 * close_file() returns the unix errno if an error
2770 * was detected on close - normally this is due to
2771 * a disk full error. If not then it was probably an I/O error.
2774 if((close_err = close_file(fsp,True)) != 0) {
2776 END_PROFILE(SMBclose);
2777 return (UNIXERROR(ERRHRD,ERRgeneral));
2781 * Now take care of any time sent in the close.
2784 mtime = make_unix_date3(inbuf+smb_vwv1);
2786 /* try and set the date */
2787 set_filetime(conn, file_name, mtime);
2791 /* We have a cached error */
2793 END_PROFILE(SMBclose);
2794 return ERROR_DOS(eclass,err);
2797 END_PROFILE(SMBclose);
2801 /****************************************************************************
2802 Reply to a writeclose (Core+ protocol).
2803 ****************************************************************************/
2805 int reply_writeclose(connection_struct *conn,
2806 char *inbuf,char *outbuf, int size, int dum_buffsize)
2809 ssize_t nwritten = -1;
2815 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2816 START_PROFILE(SMBwriteclose);
2818 CHECK_FSP(fsp,conn);
2821 numtowrite = SVAL(inbuf,smb_vwv1);
2822 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2823 mtime = make_unix_date3(inbuf+smb_vwv4);
2824 data = smb_buf(inbuf) + 1;
2826 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2827 END_PROFILE(SMBwriteclose);
2828 return ERROR_DOS(ERRDOS,ERRlock);
2831 nwritten = write_file(fsp,data,startpos,numtowrite);
2833 set_filetime(conn, fsp->fsp_name,mtime);
2836 * More insanity. W2K only closes the file if writelen > 0.
2841 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2843 close_err = close_file(fsp,True);
2846 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2847 fsp->fnum, (int)numtowrite, (int)nwritten,
2848 conn->num_files_open));
2850 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2851 END_PROFILE(SMBwriteclose);
2852 return(UNIXERROR(ERRHRD,ERRdiskfull));
2855 if(close_err != 0) {
2857 END_PROFILE(SMBwriteclose);
2858 return(UNIXERROR(ERRHRD,ERRgeneral));
2861 outsize = set_message(outbuf,1,0,True);
2863 SSVAL(outbuf,smb_vwv0,nwritten);
2864 END_PROFILE(SMBwriteclose);
2868 /****************************************************************************
2870 ****************************************************************************/
2872 int reply_lock(connection_struct *conn,
2873 char *inbuf,char *outbuf, int length, int dum_buffsize)
2875 int outsize = set_message(outbuf,0,0,True);
2876 SMB_BIG_UINT count,offset;
2878 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2879 BOOL my_lock_ctx = False;
2881 START_PROFILE(SMBlock);
2883 CHECK_FSP(fsp,conn);
2885 release_level_2_oplocks_on_change(fsp);
2887 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2888 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2890 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2891 fsp->fd, fsp->fnum, (double)offset, (double)count));
2893 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2894 if (NT_STATUS_V(status)) {
2896 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2897 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2899 * A blocking lock was requested. Package up
2900 * this smb into a queued request and push it
2901 * onto the blocking lock queue.
2903 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2904 END_PROFILE(SMBlock);
2909 END_PROFILE(SMBlock);
2910 return ERROR_NT(status);
2913 END_PROFILE(SMBlock);
2917 /****************************************************************************
2919 ****************************************************************************/
2921 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2924 int outsize = set_message(outbuf,0,0,True);
2925 SMB_BIG_UINT count,offset;
2927 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2928 START_PROFILE(SMBunlock);
2930 CHECK_FSP(fsp,conn);
2932 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2933 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2935 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2936 if (NT_STATUS_V(status)) {
2937 END_PROFILE(SMBunlock);
2938 return ERROR_NT(status);
2941 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2942 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2944 END_PROFILE(SMBunlock);
2948 /****************************************************************************
2950 ****************************************************************************/
2952 int reply_tdis(connection_struct *conn,
2953 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2955 int outsize = set_message(outbuf,0,0,True);
2957 START_PROFILE(SMBtdis);
2959 vuid = SVAL(inbuf,smb_uid);
2962 DEBUG(4,("Invalid connection in tdis\n"));
2963 END_PROFILE(SMBtdis);
2964 return ERROR_DOS(ERRSRV,ERRinvnid);
2969 close_cnum(conn,vuid);
2971 END_PROFILE(SMBtdis);
2975 /****************************************************************************
2977 ****************************************************************************/
2979 int reply_echo(connection_struct *conn,
2980 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2982 int smb_reverb = SVAL(inbuf,smb_vwv0);
2984 unsigned int data_len = smb_buflen(inbuf);
2985 int outsize = set_message(outbuf,1,data_len,True);
2986 START_PROFILE(SMBecho);
2988 if (data_len > BUFFER_SIZE) {
2989 DEBUG(0,("reply_echo: data_len too large.\n"));
2990 END_PROFILE(SMBecho);
2994 /* copy any incoming data back out */
2996 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2998 if (smb_reverb > 100) {
2999 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3003 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3004 SSVAL(outbuf,smb_vwv0,seq_num);
3006 smb_setlen(outbuf,outsize - 4);
3008 if (!send_smb(smbd_server_fd(),outbuf))
3009 exit_server("reply_echo: send_smb failed.");
3012 DEBUG(3,("echo %d times\n", smb_reverb));
3016 END_PROFILE(SMBecho);
3020 /****************************************************************************
3021 Reply to a printopen.
3022 ****************************************************************************/
3024 int reply_printopen(connection_struct *conn,
3025 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3029 START_PROFILE(SMBsplopen);
3031 if (!CAN_PRINT(conn)) {
3032 END_PROFILE(SMBsplopen);
3033 return ERROR_DOS(ERRDOS,ERRnoaccess);
3036 /* Open for exclusive use, write only. */
3037 fsp = print_fsp_open(conn, NULL);
3040 END_PROFILE(SMBsplopen);
3041 return(UNIXERROR(ERRDOS,ERRnoaccess));
3044 outsize = set_message(outbuf,1,0,True);
3045 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3047 DEBUG(3,("openprint fd=%d fnum=%d\n",
3048 fsp->fd, fsp->fnum));
3050 END_PROFILE(SMBsplopen);
3054 /****************************************************************************
3055 Reply to a printclose.
3056 ****************************************************************************/
3058 int reply_printclose(connection_struct *conn,
3059 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3061 int outsize = set_message(outbuf,0,0,True);
3062 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3064 START_PROFILE(SMBsplclose);
3066 CHECK_FSP(fsp,conn);
3068 if (!CAN_PRINT(conn)) {
3069 END_PROFILE(SMBsplclose);
3070 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3073 DEBUG(3,("printclose fd=%d fnum=%d\n",
3074 fsp->fd,fsp->fnum));
3076 close_err = close_file(fsp,True);
3078 if(close_err != 0) {
3080 END_PROFILE(SMBsplclose);
3081 return(UNIXERROR(ERRHRD,ERRgeneral));
3084 END_PROFILE(SMBsplclose);
3088 /****************************************************************************
3089 Reply to a printqueue.
3090 ****************************************************************************/
3092 int reply_printqueue(connection_struct *conn,
3093 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3095 int outsize = set_message(outbuf,2,3,True);
3096 int max_count = SVAL(inbuf,smb_vwv0);
3097 int start_index = SVAL(inbuf,smb_vwv1);
3098 START_PROFILE(SMBsplretq);
3100 /* we used to allow the client to get the cnum wrong, but that
3101 is really quite gross and only worked when there was only
3102 one printer - I think we should now only accept it if they
3103 get it right (tridge) */
3104 if (!CAN_PRINT(conn)) {
3105 END_PROFILE(SMBsplretq);
3106 return ERROR_DOS(ERRDOS,ERRnoaccess);
3109 SSVAL(outbuf,smb_vwv0,0);
3110 SSVAL(outbuf,smb_vwv1,0);
3111 SCVAL(smb_buf(outbuf),0,1);
3112 SSVAL(smb_buf(outbuf),1,0);
3114 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3115 start_index, max_count));
3118 print_queue_struct *queue = NULL;
3119 print_status_struct status;
3120 char *p = smb_buf(outbuf) + 3;
3121 int count = print_queue_status(SNUM(conn), &queue, &status);
3122 int num_to_get = ABS(max_count);
3123 int first = (max_count>0?start_index:start_index+max_count+1);
3129 num_to_get = MIN(num_to_get,count-first);
3132 for (i=first;i<first+num_to_get;i++) {
3133 put_dos_date2(p,0,queue[i].time);
3134 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3135 SSVAL(p,5, queue[i].job);
3136 SIVAL(p,7,queue[i].size);
3138 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3143 outsize = set_message(outbuf,2,28*count+3,False);
3144 SSVAL(outbuf,smb_vwv0,count);
3145 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3146 SCVAL(smb_buf(outbuf),0,1);
3147 SSVAL(smb_buf(outbuf),1,28*count);
3152 DEBUG(3,("%d entries returned in queue\n",count));
3155 END_PROFILE(SMBsplretq);
3159 /****************************************************************************
3160 Reply to a printwrite.
3161 ****************************************************************************/
3163 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3166 int outsize = set_message(outbuf,0,0,True);
3168 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3170 START_PROFILE(SMBsplwr);
3172 if (!CAN_PRINT(conn)) {
3173 END_PROFILE(SMBsplwr);
3174 return ERROR_DOS(ERRDOS,ERRnoaccess);
3177 CHECK_FSP(fsp,conn);
3180 numtowrite = SVAL(smb_buf(inbuf),1);
3181 data = smb_buf(inbuf) + 3;
3183 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3184 END_PROFILE(SMBsplwr);
3185 return(UNIXERROR(ERRHRD,ERRdiskfull));
3188 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3190 END_PROFILE(SMBsplwr);
3194 /****************************************************************************
3195 The guts of the mkdir command, split out so it may be called by the NT SMB
3197 ****************************************************************************/
3199 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3201 BOOL bad_path = False;
3202 SMB_STRUCT_STAT sbuf;
3205 unix_convert(directory,conn,0,&bad_path,&sbuf);
3207 if( strchr_m(directory, ':')) {
3208 return NT_STATUS_NOT_A_DIRECTORY;
3211 if (ms_has_wild(directory)) {
3212 return NT_STATUS_OBJECT_NAME_INVALID;
3216 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3219 if (check_name(directory, conn))
3220 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3223 if(errno == ENOENT) {
3224 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3226 return map_nt_error_from_unix(errno);
3229 return NT_STATUS_OK;
3232 /****************************************************************************
3234 ****************************************************************************/
3236 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3241 START_PROFILE(SMBmkdir);
3243 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3244 if (!NT_STATUS_IS_OK(status)) {
3245 END_PROFILE(SMBmkdir);
3246 return ERROR_NT(status);
3249 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3251 status = mkdir_internal(conn, directory);
3252 if (!NT_STATUS_IS_OK(status)) {
3253 END_PROFILE(SMBmkdir);
3254 return ERROR_NT(status);
3257 outsize = set_message(outbuf,0,0,True);
3259 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3261 END_PROFILE(SMBmkdir);
3265 /****************************************************************************
3266 Static function used by reply_rmdir to delete an entire directory
3267 tree recursively. Return False on ok, True on fail.
3268 ****************************************************************************/
3270 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3272 const char *dname = NULL;
3274 void *dirptr = OpenDir(conn, directory, False);
3279 while((dname = ReadDirName(dirptr))) {
3283 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3286 /* Construct the full name. */
3287 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3293 pstrcpy(fullname, directory);
3294 pstrcat(fullname, "/");
3295 pstrcat(fullname, dname);
3297 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3302 if(st.st_mode & S_IFDIR) {
3303 if(recursive_rmdir(conn, fullname)!=0) {
3307 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3311 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3320 /****************************************************************************
3321 The internals of the rmdir code - called elsewhere.
3322 ****************************************************************************/
3324 BOOL rmdir_internals(connection_struct *conn, char *directory)
3328 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3329 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3331 * Check to see if the only thing in this directory are
3332 * vetoed files/directories. If so then delete them and
3333 * retry. If we fail to delete any of them (and we *don't*
3334 * do a recursive delete) then fail the rmdir.
3336 BOOL all_veto_files = True;
3338 void *dirptr = OpenDir(conn, directory, False);
3340 if(dirptr != NULL) {
3341 int dirpos = TellDir(dirptr);
3342 while ((dname = ReadDirName(dirptr))) {
3343 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3345 if(!IS_VETO_PATH(conn, dname)) {
3346 all_veto_files = False;
3351 if(all_veto_files) {
3352 SeekDir(dirptr,dirpos);
3353 while ((dname = ReadDirName(dirptr))) {
3357 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3360 /* Construct the full name. */
3361 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3366 pstrcpy(fullname, directory);
3367 pstrcat(fullname, "/");
3368 pstrcat(fullname, dname);
3370 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3372 if(st.st_mode & S_IFDIR) {
3373 if(lp_recursive_veto_delete(SNUM(conn))) {
3374 if(recursive_rmdir(conn, fullname) != 0)
3377 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3379 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3383 /* Retry the rmdir */
3384 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3394 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3399 /****************************************************************************
3401 ****************************************************************************/
3403 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3408 BOOL bad_path = False;
3409 SMB_STRUCT_STAT sbuf;
3411 START_PROFILE(SMBrmdir);
3413 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 END_PROFILE(SMBrmdir);
3416 return ERROR_NT(status);
3419 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3421 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3423 END_PROFILE(SMBrmdir);
3424 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3427 if (check_name(directory,conn)) {
3428 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3429 ok = rmdir_internals(conn, directory);
3433 END_PROFILE(SMBrmdir);
3434 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3437 outsize = set_message(outbuf,0,0,True);
3439 DEBUG( 3, ( "rmdir %s\n", directory ) );
3441 END_PROFILE(SMBrmdir);
3445 /*******************************************************************
3446 Resolve wildcards in a filename rename.
3447 Note that name is in UNIX charset and thus potentially can be more
3448 than fstring buffer (255 bytes) especially in default UTF-8 case.
3449 Therefore, we use pstring inside and all calls should ensure that
3450 name2 is at least pstring-long (they do already)
3451 ********************************************************************/
3453 static BOOL resolve_wildcards(const char *name1, char *name2)
3455 pstring root1,root2;
3457 char *p,*p2, *pname1, *pname2;
3458 int available_space, actual_space;
3461 pname1 = strrchr_m(name1,'/');
3462 pname2 = strrchr_m(name2,'/');
3464 if (!pname1 || !pname2)
3467 pstrcpy(root1,pname1);
3468 pstrcpy(root2,pname2);
3469 p = strrchr_m(root1,'.');
3476 p = strrchr_m(root2,'.');
3490 } else if (*p2 == '*') {
3506 } else if (*p2 == '*') {
3516 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3519 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3520 if (actual_space >= available_space - 1) {
3521 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3522 actual_space - available_space));
3525 pstrcpy_base(pname2, root2, name2);
3531 /****************************************************************************
3532 Ensure open files have their names updates.
3533 ****************************************************************************/
3535 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3538 BOOL did_rename = False;
3540 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3541 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3542 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3543 fsp->fsp_name, newname ));
3544 string_set(&fsp->fsp_name, newname);
3549 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3550 (unsigned int)dev, (double)inode, newname ));
3553 /****************************************************************************
3554 Rename an open file - given an fsp.
3555 ****************************************************************************/
3557 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3559 SMB_STRUCT_STAT sbuf;
3560 BOOL bad_path = False;
3561 pstring newname_last_component;
3562 NTSTATUS error = NT_STATUS_OK;
3567 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3569 /* Quick check for "." and ".." */
3570 if (!bad_path && newname_last_component[0] == '.') {
3571 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3572 return NT_STATUS_ACCESS_DENIED;
3575 if (!rcdest && bad_path) {
3576 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3579 /* Ensure newname contains a '/' */
3580 if(strrchr_m(newname,'/') == 0) {
3583 pstrcpy(tmpstr, "./");
3584 pstrcat(tmpstr, newname);
3585 pstrcpy(newname, tmpstr);
3589 * Check for special case with case preserving and not
3590 * case sensitive. If the old last component differs from the original
3591 * last component only by case, then we should allow
3592 * the rename (user is trying to change the case of the
3596 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3597 strequal(newname, fsp->fsp_name)) {
3599 pstring newname_modified_last_component;
3602 * Get the last component of the modified name.
3603 * Note that we guarantee that newname contains a '/'
3606 p = strrchr_m(newname,'/');
3607 pstrcpy(newname_modified_last_component,p+1);
3609 if(strcsequal(newname_modified_last_component,
3610 newname_last_component) == False) {
3612 * Replace the modified last component with
3615 pstrcpy(p+1, newname_last_component);
3620 * If the src and dest names are identical - including case,
3621 * don't do the rename, just return success.
3624 if (strcsequal(fsp->fsp_name, newname)) {
3625 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3627 return NT_STATUS_OK;
3630 dest_exists = vfs_object_exist(conn,newname,NULL);
3632 if(!replace_if_exists && dest_exists) {
3633 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3634 fsp->fsp_name,newname));
3635 return NT_STATUS_OBJECT_NAME_COLLISION;
3638 error = can_rename(newname,conn,attrs,&sbuf);
3640 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3641 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3642 nt_errstr(error), fsp->fsp_name,newname));
3643 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3644 error = NT_STATUS_ACCESS_DENIED;
3648 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3649 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3650 fsp->fsp_name,newname));
3651 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3652 return NT_STATUS_OK;
3655 if (errno == ENOTDIR || errno == EISDIR)
3656 error = NT_STATUS_OBJECT_NAME_COLLISION;
3658 error = map_nt_error_from_unix(errno);
3660 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3661 nt_errstr(error), fsp->fsp_name,newname));
3666 /****************************************************************************
3667 The guts of the rename command, split out so it may be called by the NT SMB
3669 ****************************************************************************/
3671 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3675 pstring last_component_src;
3676 pstring last_component_dest;
3679 BOOL bad_path_src = False;
3680 BOOL bad_path_dest = False;
3682 NTSTATUS error = NT_STATUS_OK;
3685 SMB_STRUCT_STAT sbuf1, sbuf2;
3687 *directory = *mask = 0;
3692 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3693 if (!rc && bad_path_src) {
3694 if (ms_has_wild(last_component_src))
3695 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3696 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3699 /* Quick check for "." and ".." */
3700 if (last_component_src[0] == '.') {
3701 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3702 return NT_STATUS_OBJECT_NAME_INVALID;
3706 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3708 /* Quick check for "." and ".." */
3709 if (last_component_dest[0] == '.') {
3710 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3711 return NT_STATUS_OBJECT_NAME_INVALID;
3716 * Split the old name into directory and last component
3717 * strings. Note that unix_convert may have stripped off a
3718 * leading ./ from both name and newname if the rename is
3719 * at the root of the share. We need to make sure either both
3720 * name and newname contain a / character or neither of them do
3721 * as this is checked in resolve_wildcards().
3724 p = strrchr_m(name,'/');
3726 pstrcpy(directory,".");
3730 pstrcpy(directory,name);
3732 *p = '/'; /* Replace needed for exceptional test below. */
3736 * We should only check the mangled cache
3737 * here if unix_convert failed. This means
3738 * that the path in 'mask' doesn't exist
3739 * on the file system and so we need to look
3740 * for a possible mangle. This patch from
3741 * Tine Smukavec <valentin.smukavec@hermes.si>.
3744 if (!rc && mangle_is_mangled(mask))
3745 mangle_check_cache( mask, sizeof(pstring)-1 );
3747 has_wild = ms_has_wild(mask);
3751 * No wildcards - just process the one file.
3753 BOOL is_short_name = mangle_is_8_3(name, True);
3755 /* Add a terminating '/' to the directory name. */
3756 pstrcat(directory,"/");
3757 pstrcat(directory,mask);
3759 /* Ensure newname contains a '/' also */
3760 if(strrchr_m(newname,'/') == 0) {
3763 pstrcpy(tmpstr, "./");
3764 pstrcat(tmpstr, newname);
3765 pstrcpy(newname, tmpstr);
3768 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3769 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3770 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3771 newname, last_component_dest, is_short_name));
3774 * Check for special case with case preserving and not
3775 * case sensitive, if directory and newname are identical,
3776 * and the old last component differs from the original
3777 * last component only by case, then we should allow
3778 * the rename (user is trying to change the case of the
3781 if((conn->case_sensitive == False) &&
3782 (((conn->case_preserve == True) &&
3783 (is_short_name == False)) ||
3784 ((conn->short_case_preserve == True) &&
3785 (is_short_name == True))) &&
3786 strcsequal(directory, newname)) {
3787 pstring modified_last_component;
3790 * Get the last component of the modified name.
3791 * Note that we guarantee that newname contains a '/'
3794 p = strrchr_m(newname,'/');
3795 pstrcpy(modified_last_component,p+1);
3797 if(strcsequal(modified_last_component,
3798 last_component_dest) == False) {
3800 * Replace the modified last component with
3803 pstrcpy(p+1, last_component_dest);
3807 resolve_wildcards(directory,newname);
3810 * The source object must exist.
3813 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3814 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3815 directory,newname));
3817 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3819 * Must return different errors depending on whether the parent
3820 * directory existed or not.
3823 p = strrchr_m(directory, '/');
3825 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3827 if (vfs_object_exist(conn, directory, NULL))
3828 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3829 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3831 error = map_nt_error_from_unix(errno);
3832 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3833 nt_errstr(error), directory,newname));
3838 if (!rcdest && bad_path_dest) {
3839 if (ms_has_wild(last_component_dest))
3840 return NT_STATUS_OBJECT_NAME_INVALID;
3841 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3844 error = can_rename(directory,conn,attrs,&sbuf1);
3846 if (!NT_STATUS_IS_OK(error)) {
3847 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3848 nt_errstr(error), directory,newname));
3853 * If the src and dest names are identical - including case,
3854 * don't do the rename, just return success.
3857 if (strcsequal(directory, newname)) {
3858 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3859 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3860 return NT_STATUS_OK;
3863 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3864 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3865 directory,newname));
3866 return NT_STATUS_OBJECT_NAME_COLLISION;
3869 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3870 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3871 directory,newname));
3872 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3873 return NT_STATUS_OK;
3876 if (errno == ENOTDIR || errno == EISDIR)
3877 error = NT_STATUS_OBJECT_NAME_COLLISION;
3879 error = map_nt_error_from_unix(errno);
3881 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3882 nt_errstr(error), directory,newname));
3887 * Wildcards - process each file that matches.
3889 void *dirptr = NULL;
3893 if (check_name(directory,conn))
3894 dirptr = OpenDir(conn, directory, True);
3897 error = NT_STATUS_NO_SUCH_FILE;
3898 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3900 if (strequal(mask,"????????.???"))
3903 while ((dname = ReadDirName(dirptr))) {
3905 BOOL sysdir_entry = False;
3907 pstrcpy(fname,dname);
3909 /* Quick check for "." and ".." */
3910 if (fname[0] == '.') {
3911 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3913 sysdir_entry = True;
3920 if(!mask_match(fname, mask, conn->case_sensitive))
3924 error = NT_STATUS_OBJECT_NAME_INVALID;
3928 error = NT_STATUS_ACCESS_DENIED;
3929 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3930 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3931 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3932 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3935 error = can_rename(fname,conn,attrs,&sbuf1);
3936 if (!NT_STATUS_IS_OK(error)) {
3937 DEBUG(6,("rename %s refused\n", fname));
3940 pstrcpy(destname,newname);
3942 if (!resolve_wildcards(fname,destname)) {
3943 DEBUG(6,("resolve_wildcards %s %s failed\n",
3948 if (strcsequal(fname,destname)) {
3949 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3950 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3952 error = NT_STATUS_OK;
3956 if (!replace_if_exists &&
3957 vfs_file_exist(conn,destname, NULL)) {
3958 DEBUG(6,("file_exist %s\n", destname));
3959 error = NT_STATUS_OBJECT_NAME_COLLISION;
3963 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3964 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3966 error = NT_STATUS_OK;
3968 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3973 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3974 if (!rcdest && bad_path_dest) {
3975 if (ms_has_wild(last_component_dest))
3976 return NT_STATUS_OBJECT_NAME_INVALID;
3977 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3982 if (count == 0 && NT_STATUS_IS_OK(error)) {
3983 error = map_nt_error_from_unix(errno);
3989 /****************************************************************************
3991 ****************************************************************************/
3993 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4000 uint16 attrs = SVAL(inbuf,smb_vwv0);
4003 START_PROFILE(SMBmv);
4005 p = smb_buf(inbuf) + 1;
4006 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4007 if (!NT_STATUS_IS_OK(status)) {
4009 return ERROR_NT(status);
4012 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4013 if (!NT_STATUS_IS_OK(status)) {
4015 return ERROR_NT(status);
4018 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4019 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4021 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4023 status = rename_internals(conn, name, newname, attrs, False);
4024 if (!NT_STATUS_IS_OK(status)) {
4026 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4027 /* We have re-scheduled this call. */
4028 clear_cached_errors();
4031 return ERROR_NT(status);
4035 * Win2k needs a changenotify request response before it will
4036 * update after a rename..
4038 process_pending_change_notify_queue((time_t)0);
4039 outsize = set_message(outbuf,0,0,True);
4045 /*******************************************************************
4046 Copy a file as part of a reply_copy.
4047 ******************************************************************/
4049 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4050 int count,BOOL target_is_directory, int *err_ret)
4053 SMB_STRUCT_STAT src_sbuf, sbuf2;
4055 files_struct *fsp1,*fsp2;
4061 pstrcpy(dest,dest1);
4062 if (target_is_directory) {
4063 char *p = strrchr_m(src,'/');
4072 if (!vfs_file_exist(conn,src,&src_sbuf))
4075 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4076 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4082 if (!target_is_directory && count)
4083 ofun = FILE_EXISTS_OPEN;
4085 dosattrs = dos_mode(conn, src, &src_sbuf);
4086 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4087 ZERO_STRUCTP(&sbuf2);
4089 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4090 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4093 close_file(fsp1,False);
4097 if ((ofun&3) == 1) {
4098 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4099 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4101 * Stop the copy from occurring.
4104 src_sbuf.st_size = 0;
4108 if (src_sbuf.st_size)
4109 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4111 close_file(fsp1,False);
4113 /* Ensure the modtime is set correctly on the destination file. */
4114 fsp2->pending_modtime = src_sbuf.st_mtime;
4117 * As we are opening fsp1 read-only we only expect
4118 * an error on close on fsp2 if we are out of space.
4119 * Thus we don't look at the error return from the
4122 *err_ret = close_file(fsp2,False);
4124 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4127 /****************************************************************************
4128 Reply to a file copy.
4129 ****************************************************************************/
4131 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4136 pstring mask,newname;
4139 int error = ERRnoaccess;
4143 int tid2 = SVAL(inbuf,smb_vwv0);
4144 int ofun = SVAL(inbuf,smb_vwv1);
4145 int flags = SVAL(inbuf,smb_vwv2);
4146 BOOL target_is_directory=False;
4147 BOOL bad_path1 = False;
4148 BOOL bad_path2 = False;
4150 SMB_STRUCT_STAT sbuf1, sbuf2;
4153 START_PROFILE(SMBcopy);
4155 *directory = *mask = 0;
4158 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4159 if (!NT_STATUS_IS_OK(status)) {
4160 END_PROFILE(SMBcopy);
4161 return ERROR_NT(status);
4163 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4164 if (!NT_STATUS_IS_OK(status)) {
4165 END_PROFILE(SMBcopy);
4166 return ERROR_NT(status);
4169 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4171 if (tid2 != conn->cnum) {
4172 /* can't currently handle inter share copies XXXX */
4173 DEBUG(3,("Rejecting inter-share copy\n"));
4174 END_PROFILE(SMBcopy);
4175 return ERROR_DOS(ERRSRV,ERRinvdevice);
4178 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4179 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4181 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4182 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4184 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4186 if ((flags&1) && target_is_directory) {
4187 END_PROFILE(SMBcopy);
4188 return ERROR_DOS(ERRDOS,ERRbadfile);
4191 if ((flags&2) && !target_is_directory) {
4192 END_PROFILE(SMBcopy);
4193 return ERROR_DOS(ERRDOS,ERRbadpath);
4196 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4197 /* wants a tree copy! XXXX */
4198 DEBUG(3,("Rejecting tree copy\n"));
4199 END_PROFILE(SMBcopy);
4200 return ERROR_DOS(ERRSRV,ERRerror);
4203 p = strrchr_m(name,'/');
4205 pstrcpy(directory,"./");
4209 pstrcpy(directory,name);
4214 * We should only check the mangled cache
4215 * here if unix_convert failed. This means
4216 * that the path in 'mask' doesn't exist
4217 * on the file system and so we need to look
4218 * for a possible mangle. This patch from
4219 * Tine Smukavec <valentin.smukavec@hermes.si>.
4222 if (!rc && mangle_is_mangled(mask))
4223 mangle_check_cache( mask, sizeof(pstring)-1 );
4225 has_wild = ms_has_wild(mask);
4228 pstrcat(directory,"/");
4229 pstrcat(directory,mask);
4230 if (resolve_wildcards(directory,newname) &&
4231 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4235 END_PROFILE(SMBcopy);
4236 return(UNIXERROR(ERRHRD,ERRgeneral));
4239 exists = vfs_file_exist(conn,directory,NULL);
4242 void *dirptr = NULL;
4246 if (check_name(directory,conn))
4247 dirptr = OpenDir(conn, directory, True);
4252 if (strequal(mask,"????????.???"))
4255 while ((dname = ReadDirName(dirptr))) {
4257 pstrcpy(fname,dname);
4259 if(!mask_match(fname, mask, conn->case_sensitive))
4262 error = ERRnoaccess;
4263 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4264 pstrcpy(destname,newname);
4265 if (resolve_wildcards(fname,destname) &&
4266 copy_file(fname,destname,conn,ofun,
4267 count,target_is_directory,&err))
4269 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4277 /* Error on close... */
4279 END_PROFILE(SMBcopy);
4280 return(UNIXERROR(ERRHRD,ERRgeneral));
4284 END_PROFILE(SMBcopy);
4285 return ERROR_DOS(ERRDOS,error);
4287 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4288 unix_ERR_class = ERRDOS;
4289 unix_ERR_code = ERRbadpath;
4291 END_PROFILE(SMBcopy);
4292 return(UNIXERROR(ERRDOS,error));
4296 outsize = set_message(outbuf,1,0,True);
4297 SSVAL(outbuf,smb_vwv0,count);
4299 END_PROFILE(SMBcopy);
4303 /****************************************************************************
4305 ****************************************************************************/
4307 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4315 START_PROFILE(pathworks_setdir);
4318 if (!CAN_SETDIR(snum)) {
4319 END_PROFILE(pathworks_setdir);
4320 return ERROR_DOS(ERRDOS,ERRnoaccess);
4323 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4324 if (!NT_STATUS_IS_OK(status)) {
4325 END_PROFILE(pathworks_setdir);
4326 return ERROR_NT(status);
4329 if (strlen(newdir) == 0) {
4332 ok = vfs_directory_exist(conn,newdir,NULL);
4334 string_set(&conn->connectpath,newdir);
4338 END_PROFILE(pathworks_setdir);
4339 return ERROR_DOS(ERRDOS,ERRbadpath);
4342 outsize = set_message(outbuf,0,0,True);
4343 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4345 DEBUG(3,("setdir %s\n", newdir));
4347 END_PROFILE(pathworks_setdir);
4351 /****************************************************************************
4352 Get a lock pid, dealing with large count requests.
4353 ****************************************************************************/
4355 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4357 if(!large_file_format)
4358 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4360 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4363 /****************************************************************************
4364 Get a lock count, dealing with large count requests.
4365 ****************************************************************************/
4367 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4369 SMB_BIG_UINT count = 0;
4371 if(!large_file_format) {
4372 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4375 #if defined(HAVE_LONGLONG)
4376 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4377 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4378 #else /* HAVE_LONGLONG */
4381 * NT4.x seems to be broken in that it sends large file (64 bit)
4382 * lockingX calls even if the CAP_LARGE_FILES was *not*
4383 * negotiated. For boxes without large unsigned ints truncate the
4384 * lock count by dropping the top 32 bits.
4387 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4388 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4389 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4390 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4391 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4394 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4395 #endif /* HAVE_LONGLONG */
4401 #if !defined(HAVE_LONGLONG)
4402 /****************************************************************************
4403 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4404 ****************************************************************************/
4406 static uint32 map_lock_offset(uint32 high, uint32 low)
4410 uint32 highcopy = high;
4413 * Try and find out how many significant bits there are in high.
4416 for(i = 0; highcopy; i++)
4420 * We use 31 bits not 32 here as POSIX
4421 * lock offsets may not be negative.
4424 mask = (~0) << (31 - i);
4427 return 0; /* Fail. */
4433 #endif /* !defined(HAVE_LONGLONG) */
4435 /****************************************************************************
4436 Get a lock offset, dealing with large offset requests.
4437 ****************************************************************************/
4439 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4441 SMB_BIG_UINT offset = 0;
4445 if(!large_file_format) {
4446 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4449 #if defined(HAVE_LONGLONG)
4450 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4451 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4452 #else /* HAVE_LONGLONG */
4455 * NT4.x seems to be broken in that it sends large file (64 bit)
4456 * lockingX calls even if the CAP_LARGE_FILES was *not*
4457 * negotiated. For boxes without large unsigned ints mangle the
4458 * lock offset by mapping the top 32 bits onto the lower 32.
4461 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4462 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4463 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4466 if((new_low = map_lock_offset(high, low)) == 0) {
4468 return (SMB_BIG_UINT)-1;
4471 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4472 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4473 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4474 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4477 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4478 #endif /* HAVE_LONGLONG */
4484 /****************************************************************************
4485 Reply to a lockingX request.
4486 ****************************************************************************/
4488 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4490 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4491 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4492 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4493 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4494 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4495 SMB_BIG_UINT count = 0, offset = 0;
4497 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4500 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4502 BOOL my_lock_ctx = False;
4505 START_PROFILE(SMBlockingX);
4507 CHECK_FSP(fsp,conn);
4509 data = smb_buf(inbuf);
4511 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4512 /* we don't support these - and CANCEL_LOCK makes w2k
4513 and XP reboot so I don't really want to be
4514 compatible! (tridge) */
4515 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4518 /* Check if this is an oplock break on a file
4519 we have granted an oplock on.
4521 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4522 /* Client can insist on breaking to none. */
4523 BOOL break_to_none = (oplocklevel == 0);
4525 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4526 (unsigned int)oplocklevel, fsp->fnum ));
4529 * Make sure we have granted an exclusive or batch oplock on this file.
4532 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4533 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4534 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4536 /* if this is a pure oplock break request then don't send a reply */
4537 if (num_locks == 0 && num_ulocks == 0) {
4538 END_PROFILE(SMBlockingX);
4541 END_PROFILE(SMBlockingX);
4542 return ERROR_DOS(ERRDOS,ERRlock);
4546 if (remove_oplock(fsp, break_to_none) == False) {
4547 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4551 /* if this is a pure oplock break request then don't send a reply */
4552 if (num_locks == 0 && num_ulocks == 0) {
4553 /* Sanity check - ensure a pure oplock break is not a
4555 if(CVAL(inbuf,smb_vwv0) != 0xff)
4556 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4557 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4558 END_PROFILE(SMBlockingX);
4564 * We do this check *after* we have checked this is not a oplock break
4565 * response message. JRA.
4568 release_level_2_oplocks_on_change(fsp);
4570 /* Data now points at the beginning of the list
4571 of smb_unlkrng structs */
4572 for(i = 0; i < (int)num_ulocks; i++) {
4573 lock_pid = get_lock_pid( data, i, large_file_format);
4574 count = get_lock_count( data, i, large_file_format);
4575 offset = get_lock_offset( data, i, large_file_format, &err);
4578 * There is no error code marked "stupid client bug".... :-).
4581 END_PROFILE(SMBlockingX);
4582 return ERROR_DOS(ERRDOS,ERRnoaccess);
4585 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4586 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4588 status = do_unlock(fsp,conn,lock_pid,count,offset);
4589 if (NT_STATUS_V(status)) {
4590 END_PROFILE(SMBlockingX);
4591 return ERROR_NT(status);
4595 /* Setup the timeout in seconds. */
4597 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4599 /* Now do any requested locks */
4600 data += ((large_file_format ? 20 : 10)*num_ulocks);
4602 /* Data now points at the beginning of the list
4603 of smb_lkrng structs */
4605 for(i = 0; i < (int)num_locks; i++) {
4606 lock_pid = get_lock_pid( data, i, large_file_format);
4607 count = get_lock_count( data, i, large_file_format);
4608 offset = get_lock_offset( data, i, large_file_format, &err);
4611 * There is no error code marked "stupid client bug".... :-).
4614 END_PROFILE(SMBlockingX);
4615 return ERROR_DOS(ERRDOS,ERRnoaccess);
4618 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4619 (double)offset, (double)count, (unsigned int)lock_pid,
4620 fsp->fsp_name, (int)lock_timeout ));
4622 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4623 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4624 if (NT_STATUS_V(status)) {
4626 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4627 * Even if it's our own lock context, we need to wait here as
4628 * there may be an unlock on the way.
4629 * So I removed a "&& !my_lock_ctx" from the following
4630 * if statement. JRA.
4632 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4634 * A blocking lock was requested. Package up
4635 * this smb into a queued request and push it
4636 * onto the blocking lock queue.
4638 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4639 END_PROFILE(SMBlockingX);
4647 /* If any of the above locks failed, then we must unlock
4648 all of the previous locks (X/Open spec). */
4649 if (i != num_locks && num_locks != 0) {
4651 * Ensure we don't do a remove on the lock that just failed,
4652 * as under POSIX rules, if we have a lock already there, we
4653 * will delete it (and we shouldn't) .....
4655 for(i--; i >= 0; i--) {
4656 lock_pid = get_lock_pid( data, i, large_file_format);
4657 count = get_lock_count( data, i, large_file_format);
4658 offset = get_lock_offset( data, i, large_file_format, &err);
4661 * There is no error code marked "stupid client bug".... :-).
4664 END_PROFILE(SMBlockingX);
4665 return ERROR_DOS(ERRDOS,ERRnoaccess);
4668 do_unlock(fsp,conn,lock_pid,count,offset);
4670 END_PROFILE(SMBlockingX);
4671 return ERROR_NT(status);
4674 set_message(outbuf,2,0,True);
4676 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4677 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4679 END_PROFILE(SMBlockingX);
4680 return chain_reply(inbuf,outbuf,length,bufsize);
4683 /****************************************************************************
4684 Reply to a SMBreadbmpx (read block multiplex) request.
4685 ****************************************************************************/
4687 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4698 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4699 START_PROFILE(SMBreadBmpx);
4701 /* this function doesn't seem to work - disable by default */
4702 if (!lp_readbmpx()) {
4703 END_PROFILE(SMBreadBmpx);
4704 return ERROR_DOS(ERRSRV,ERRuseSTD);
4707 outsize = set_message(outbuf,8,0,True);
4709 CHECK_FSP(fsp,conn);
4712 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4713 maxcount = SVAL(inbuf,smb_vwv3);
4715 data = smb_buf(outbuf);
4716 pad = ((long)data)%4;
4721 max_per_packet = bufsize-(outsize+pad);
4725 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4726 END_PROFILE(SMBreadBmpx);
4727 return ERROR_DOS(ERRDOS,ERRlock);
4731 size_t N = MIN(max_per_packet,tcount-total_read);
4733 nread = read_file(fsp,data,startpos,N);
4738 if (nread < (ssize_t)N)
4739 tcount = total_read + nread;
4741 set_message(outbuf,8,nread,False);
4742 SIVAL(outbuf,smb_vwv0,startpos);
4743 SSVAL(outbuf,smb_vwv2,tcount);
4744 SSVAL(outbuf,smb_vwv6,nread);
4745 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4747 if (!send_smb(smbd_server_fd(),outbuf))
4748 exit_server("reply_readbmpx: send_smb failed.");
4750 total_read += nread;
4752 } while (total_read < (ssize_t)tcount);
4754 END_PROFILE(SMBreadBmpx);
4758 /****************************************************************************
4759 Reply to a SMBsetattrE.
4760 ****************************************************************************/
4762 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4764 struct utimbuf unix_times;
4766 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4767 START_PROFILE(SMBsetattrE);
4769 outsize = set_message(outbuf,0,0,True);
4771 if(!fsp || (fsp->conn != conn)) {
4772 END_PROFILE(SMBgetattrE);
4773 return ERROR_DOS(ERRDOS,ERRbadfid);
4777 * Convert the DOS times into unix times. Ignore create
4778 * time as UNIX can't set this.
4781 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4782 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4785 * Patch from Ray Frush <frush@engr.colostate.edu>
4786 * Sometimes times are sent as zero - ignore them.
4789 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4790 /* Ignore request */
4791 if( DEBUGLVL( 3 ) ) {
4792 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4793 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4795 END_PROFILE(SMBsetattrE);
4797 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4798 /* set modify time = to access time if modify time was 0 */
4799 unix_times.modtime = unix_times.actime;
4802 /* Set the date on this file */
4803 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4804 END_PROFILE(SMBsetattrE);
4805 return ERROR_DOS(ERRDOS,ERRnoaccess);
4808 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4809 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4811 END_PROFILE(SMBsetattrE);
4816 /* Back from the dead for OS/2..... JRA. */
4818 /****************************************************************************
4819 Reply to a SMBwritebmpx (write block multiplex primary) request.
4820 ****************************************************************************/
4822 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4825 ssize_t nwritten = -1;
4832 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4833 START_PROFILE(SMBwriteBmpx);
4835 CHECK_FSP(fsp,conn);
4839 tcount = SVAL(inbuf,smb_vwv1);
4840 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4841 write_through = BITSETW(inbuf+smb_vwv7,0);
4842 numtowrite = SVAL(inbuf,smb_vwv10);
4843 smb_doff = SVAL(inbuf,smb_vwv11);
4845 data = smb_base(inbuf) + smb_doff;
4847 /* If this fails we need to send an SMBwriteC response,
4848 not an SMBwritebmpx - set this up now so we don't forget */
4849 SCVAL(outbuf,smb_com,SMBwritec);
4851 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4852 END_PROFILE(SMBwriteBmpx);
4853 return(ERROR_DOS(ERRDOS,ERRlock));
4856 nwritten = write_file(fsp,data,startpos,numtowrite);
4858 if(lp_syncalways(SNUM(conn)) || write_through)
4859 sync_file(conn,fsp);
4861 if(nwritten < (ssize_t)numtowrite) {
4862 END_PROFILE(SMBwriteBmpx);
4863 return(UNIXERROR(ERRHRD,ERRdiskfull));
4866 /* If the maximum to be written to this file
4867 is greater than what we just wrote then set
4868 up a secondary struct to be attached to this
4869 fd, we will use this to cache error messages etc. */
4871 if((ssize_t)tcount > nwritten) {
4872 write_bmpx_struct *wbms;
4873 if(fsp->wbmpx_ptr != NULL)
4874 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4876 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4878 DEBUG(0,("Out of memory in reply_readmpx\n"));
4879 END_PROFILE(SMBwriteBmpx);
4880 return(ERROR_DOS(ERRSRV,ERRnoresource));
4882 wbms->wr_mode = write_through;
4883 wbms->wr_discard = False; /* No errors yet */
4884 wbms->wr_total_written = nwritten;
4885 wbms->wr_errclass = 0;
4887 fsp->wbmpx_ptr = wbms;
4890 /* We are returning successfully, set the message type back to
4892 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4894 outsize = set_message(outbuf,1,0,True);
4896 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4898 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4899 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4901 if (write_through && tcount==nwritten) {
4902 /* We need to send both a primary and a secondary response */
4903 smb_setlen(outbuf,outsize - 4);
4904 if (!send_smb(smbd_server_fd(),outbuf))
4905 exit_server("reply_writebmpx: send_smb failed.");
4907 /* Now the secondary */
4908 outsize = set_message(outbuf,1,0,True);
4909 SCVAL(outbuf,smb_com,SMBwritec);
4910 SSVAL(outbuf,smb_vwv0,nwritten);
4913 END_PROFILE(SMBwriteBmpx);
4917 /****************************************************************************
4918 Reply to a SMBwritebs (write block multiplex secondary) request.
4919 ****************************************************************************/
4921 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4924 ssize_t nwritten = -1;
4931 write_bmpx_struct *wbms;
4932 BOOL send_response = False;
4933 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4934 START_PROFILE(SMBwriteBs);
4936 CHECK_FSP(fsp,conn);
4939 tcount = SVAL(inbuf,smb_vwv1);
4940 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4941 numtowrite = SVAL(inbuf,smb_vwv6);
4942 smb_doff = SVAL(inbuf,smb_vwv7);
4944 data = smb_base(inbuf) + smb_doff;
4946 /* We need to send an SMBwriteC response, not an SMBwritebs */
4947 SCVAL(outbuf,smb_com,SMBwritec);
4949 /* This fd should have an auxiliary struct attached,
4950 check that it does */
4951 wbms = fsp->wbmpx_ptr;
4953 END_PROFILE(SMBwriteBs);
4957 /* If write through is set we can return errors, else we must cache them */
4958 write_through = wbms->wr_mode;
4960 /* Check for an earlier error */
4961 if(wbms->wr_discard) {
4962 END_PROFILE(SMBwriteBs);
4963 return -1; /* Just discard the packet */
4966 nwritten = write_file(fsp,data,startpos,numtowrite);
4968 if(lp_syncalways(SNUM(conn)) || write_through)
4969 sync_file(conn,fsp);
4971 if (nwritten < (ssize_t)numtowrite) {
4973 /* We are returning an error - we can delete the aux struct */
4976 fsp->wbmpx_ptr = NULL;
4977 END_PROFILE(SMBwriteBs);
4978 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4980 END_PROFILE(SMBwriteBs);
4981 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4984 /* Increment the total written, if this matches tcount
4985 we can discard the auxiliary struct (hurrah !) and return a writeC */
4986 wbms->wr_total_written += nwritten;
4987 if(wbms->wr_total_written >= tcount) {
4988 if (write_through) {
4989 outsize = set_message(outbuf,1,0,True);
4990 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4991 send_response = True;
4995 fsp->wbmpx_ptr = NULL;
4999 END_PROFILE(SMBwriteBs);
5003 END_PROFILE(SMBwriteBs);
5007 /****************************************************************************
5008 Reply to a SMBgetattrE.
5009 ****************************************************************************/
5011 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5013 SMB_STRUCT_STAT sbuf;
5016 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5017 START_PROFILE(SMBgetattrE);
5019 outsize = set_message(outbuf,11,0,True);
5021 if(!fsp || (fsp->conn != conn)) {
5022 END_PROFILE(SMBgetattrE);
5023 return ERROR_DOS(ERRDOS,ERRbadfid);
5026 /* Do an fstat on this file */
5027 if(fsp_stat(fsp, &sbuf)) {
5028 END_PROFILE(SMBgetattrE);
5029 return(UNIXERROR(ERRDOS,ERRnoaccess));
5032 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5035 * Convert the times into dos times. Set create
5036 * date to be last modify date as UNIX doesn't save
5040 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5041 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5042 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5045 SIVAL(outbuf,smb_vwv6,0);
5046 SIVAL(outbuf,smb_vwv8,0);
5048 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5049 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5050 SIVAL(outbuf,smb_vwv8,allocation_size);
5052 SSVAL(outbuf,smb_vwv10, mode);
5054 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5056 END_PROFILE(SMBgetattrE);