2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern BOOL is_unix_charset_unsafe;
37 extern int global_oplock_break;
38 unsigned int smb_echo_count = 0;
40 extern BOOL global_encrypted_passwords_negotiated;
42 /****************************************************************************
43 Ensure we check the path in *exactly* the same way as W2K.
44 We're assuming here that '/' is not the second byte in any multibyte char
45 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
47 ****************************************************************************/
49 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
52 const char *s = srcname;
53 NTSTATUS ret = NT_STATUS_OK;
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
68 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
69 /* Uh oh - "../" or "..\\" or "..\0" ! */
72 * No mb char starts with '.' so we're safe checking the directory separator here.
75 /* If we just added a '/', delete it. */
77 if ((d > destname) && (*(d-1) == '/')) {
79 if (d == (destname + 1)) {
85 /* Are we at the start ? Can't go back further if so. */
87 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
89 /* Go back one level... */
90 while (d > destname) {
96 } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
99 * No mb char starts with '.' so we're safe checking the directory separator here.
102 /* "./" or ".\\" fails with a different error depending on where it is... */
105 ret = NT_STATUS_OBJECT_NAME_INVALID;
108 return NT_STATUS_INVALID_PARAMETER;
110 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
114 /* Activate this codepath only if we know that Unix charset may contain unsafe '\\' */
115 if ((is_unix_charset_unsafe == True) && ((*s & 0x80) && IS_DIRECTORY_SEP(s[1]))) {
117 * Potential mb char with second char a directory separator.
118 * All the encodings we care about are 2 byte only, so do a
119 * conversion to unicode. If the one byte char converts then
120 * it really is a directory separator following. Otherwise if
121 * the two byte character converts (and it should or our assumption
122 * about character sets is broken and we return an error) then copy both
123 * bytes as it's a MB character, not a directory separator.
128 if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2, False) == 2) {
130 } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2, False) == 2) {
133 DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n"));
134 return NT_STATUS_INVALID_PARAMETER;
137 /* Just copy the char (or the second byte of the mb char). */
145 /****************************************************************************
146 Pull a string and check the path - provide for error return.
147 ****************************************************************************/
149 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
152 char *tmppath_ptr = tmppath;
155 SMB_ASSERT(dest_len == sizeof(pstring));
159 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
161 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
163 *err = check_path_syntax(dest, tmppath);
167 /****************************************************************************
168 Reply to a special message.
169 ****************************************************************************/
171 int reply_special(char *inbuf,char *outbuf)
174 int msg_type = CVAL(inbuf,0);
175 int msg_flags = CVAL(inbuf,1);
179 static BOOL already_got_session = False;
183 memset(outbuf,'\0',smb_size);
185 smb_setlen(outbuf,0);
188 case 0x81: /* session request */
190 if (already_got_session) {
191 exit_server("multiple session request not permitted");
194 SCVAL(outbuf,0,0x82);
196 if (name_len(inbuf+4) > 50 ||
197 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
198 DEBUG(0,("Invalid name length in session request\n"));
201 name_extract(inbuf,4,name1);
202 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
203 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
206 set_local_machine_name(name1, True);
207 set_remote_machine_name(name2, True);
209 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
210 get_local_machine_name(), get_remote_machine_name(),
213 if (name_type == 'R') {
214 /* We are being asked for a pathworks session ---
216 SCVAL(outbuf, 0,0x83);
220 /* only add the client's machine name to the list
221 of possibly valid usernames if we are operating
222 in share mode security */
223 if (lp_security() == SEC_SHARE) {
224 add_session_user(get_remote_machine_name());
227 reload_services(True);
230 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
232 already_got_session = True;
235 case 0x89: /* session keepalive request
236 (some old clients produce this?) */
237 SCVAL(outbuf,0,SMBkeepalive);
241 case 0x82: /* positive session response */
242 case 0x83: /* negative session response */
243 case 0x84: /* retarget session response */
244 DEBUG(0,("Unexpected session response\n"));
247 case SMBkeepalive: /* session keepalive */
252 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
253 msg_type, msg_flags));
258 /****************************************************************************
260 ****************************************************************************/
262 int reply_tcon(connection_struct *conn,
263 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
270 uint16 vuid = SVAL(inbuf,smb_uid);
274 DATA_BLOB password_blob;
276 START_PROFILE(SMBtcon);
278 *service_buf = *password = *dev = 0;
280 p = smb_buf(inbuf)+1;
281 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
282 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
284 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
286 p = strrchr_m(service_buf,'\\');
290 service = service_buf;
293 password_blob = data_blob(password, pwlen+1);
295 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
297 data_blob_clear_free(&password_blob);
300 END_PROFILE(SMBtcon);
301 return ERROR_NT(nt_status);
304 outsize = set_message(outbuf,2,0,True);
305 SSVAL(outbuf,smb_vwv0,max_recv);
306 SSVAL(outbuf,smb_vwv1,conn->cnum);
307 SSVAL(outbuf,smb_tid,conn->cnum);
309 DEBUG(3,("tcon service=%s cnum=%d\n",
310 service, conn->cnum));
312 END_PROFILE(SMBtcon);
316 /****************************************************************************
317 Reply to a tcon and X.
318 ****************************************************************************/
320 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
325 /* what the cleint thinks the device is */
326 fstring client_devicetype;
327 /* what the server tells the client the share represents */
328 const char *server_devicetype;
330 uint16 vuid = SVAL(inbuf,smb_uid);
331 int passlen = SVAL(inbuf,smb_vwv3);
334 extern BOOL global_encrypted_passwords_negotiated;
336 START_PROFILE(SMBtconX);
338 *service = *client_devicetype = 0;
340 /* we might have to close an old one */
341 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
342 close_cnum(conn,vuid);
345 if (passlen > MAX_PASS_LEN) {
346 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
349 if (global_encrypted_passwords_negotiated) {
350 password = data_blob(smb_buf(inbuf),passlen);
352 password = data_blob(smb_buf(inbuf),passlen+1);
353 /* Ensure correct termination */
354 password.data[passlen]=0;
357 p = smb_buf(inbuf) + passlen;
358 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
361 * the service name can be either: \\server\share
362 * or share directly like on the DELL PowerVault 705
365 q = strchr_m(path+2,'\\');
367 END_PROFILE(SMBtconX);
368 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
370 fstrcpy(service,q+1);
373 fstrcpy(service,path);
375 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
377 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
379 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
381 data_blob_clear_free(&password);
384 END_PROFILE(SMBtconX);
385 return ERROR_NT(nt_status);
389 server_devicetype = "IPC";
390 else if ( IS_PRINT(conn) )
391 server_devicetype = "LPT1:";
393 server_devicetype = "A:";
395 if (Protocol < PROTOCOL_NT1) {
396 set_message(outbuf,2,0,True);
398 p += srvstr_push(outbuf, p, server_devicetype, -1,
399 STR_TERMINATE|STR_ASCII);
400 set_message_end(outbuf,p);
402 /* NT sets the fstype of IPC$ to the null string */
403 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
405 set_message(outbuf,3,0,True);
408 p += srvstr_push(outbuf, p, server_devicetype, -1,
409 STR_TERMINATE|STR_ASCII);
410 p += srvstr_push(outbuf, p, fstype, -1,
413 set_message_end(outbuf,p);
415 /* what does setting this bit do? It is set by NT4 and
416 may affect the ability to autorun mounted cdroms */
417 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
418 (lp_csc_policy(SNUM(conn)) << 2));
420 init_dfsroot(conn, inbuf, outbuf);
424 DEBUG(3,("tconX service=%s \n",
427 /* set the incoming and outgoing tid to the just created one */
428 SSVAL(inbuf,smb_tid,conn->cnum);
429 SSVAL(outbuf,smb_tid,conn->cnum);
431 END_PROFILE(SMBtconX);
432 return chain_reply(inbuf,outbuf,length,bufsize);
435 /****************************************************************************
436 Reply to an unknown type.
437 ****************************************************************************/
439 int reply_unknown(char *inbuf,char *outbuf)
442 type = CVAL(inbuf,smb_com);
444 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
445 smb_fn_name(type), type, type));
447 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
450 /****************************************************************************
452 ****************************************************************************/
454 int reply_ioctl(connection_struct *conn,
455 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
457 uint16 device = SVAL(inbuf,smb_vwv1);
458 uint16 function = SVAL(inbuf,smb_vwv2);
459 uint32 ioctl_code = (device << 16) + function;
460 int replysize, outsize;
462 START_PROFILE(SMBioctl);
464 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
466 switch (ioctl_code) {
467 case IOCTL_QUERY_JOB_INFO:
471 END_PROFILE(SMBioctl);
472 return(ERROR_DOS(ERRSRV,ERRnosupport));
475 outsize = set_message(outbuf,8,replysize+1,True);
476 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
477 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
478 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
479 p = smb_buf(outbuf) + 1; /* Allow for alignment */
481 switch (ioctl_code) {
482 case IOCTL_QUERY_JOB_INFO:
484 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
486 END_PROFILE(SMBioctl);
487 return(UNIXERROR(ERRDOS,ERRbadfid));
489 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
490 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
491 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
496 END_PROFILE(SMBioctl);
500 /****************************************************************************
502 ****************************************************************************/
504 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
510 BOOL bad_path = False;
511 SMB_STRUCT_STAT sbuf;
514 START_PROFILE(SMBchkpth);
516 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
517 if (!NT_STATUS_IS_OK(status)) {
518 END_PROFILE(SMBchkpth);
519 return ERROR_NT(status);
522 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
524 unix_convert(name,conn,0,&bad_path,&sbuf);
526 mode = SVAL(inbuf,smb_vwv0);
528 if (check_name(name,conn)) {
529 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
530 if (!(ok = S_ISDIR(sbuf.st_mode))) {
531 END_PROFILE(SMBchkpth);
532 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
537 /* We special case this - as when a Windows machine
538 is parsing a path is steps through the components
539 one at a time - if a component fails it expects
540 ERRbadpath, not ERRbadfile.
542 if(errno == ENOENT) {
544 * Windows returns different error codes if
545 * the parent directory is valid but not the
546 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
547 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
548 * if the path is invalid.
551 END_PROFILE(SMBchkpth);
552 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
554 END_PROFILE(SMBchkpth);
555 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
557 } else if (errno == ENOTDIR) {
558 END_PROFILE(SMBchkpth);
559 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
562 END_PROFILE(SMBchkpth);
563 return(UNIXERROR(ERRDOS,ERRbadpath));
566 outsize = set_message(outbuf,0,0,True);
568 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
570 END_PROFILE(SMBchkpth);
574 /****************************************************************************
576 ****************************************************************************/
578 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
582 SMB_STRUCT_STAT sbuf;
587 BOOL bad_path = False;
591 START_PROFILE(SMBgetatr);
593 p = smb_buf(inbuf) + 1;
594 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
595 if (!NT_STATUS_IS_OK(status)) {
596 END_PROFILE(SMBgetatr);
597 return ERROR_NT(status);
600 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
602 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
603 under WfWg - weird! */
605 mode = aHIDDEN | aDIR;
606 if (!CAN_WRITE(conn))
612 unix_convert(fname,conn,0,&bad_path,&sbuf);
613 if (check_name(fname,conn)) {
614 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
615 mode = dos_mode(conn,fname,&sbuf);
617 mtime = sbuf.st_mtime;
622 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
628 END_PROFILE(SMBgetatr);
629 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
632 outsize = set_message(outbuf,10,0,True);
634 SSVAL(outbuf,smb_vwv0,mode);
635 if(lp_dos_filetime_resolution(SNUM(conn)) )
636 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
638 put_dos_date3(outbuf,smb_vwv1,mtime);
639 SIVAL(outbuf,smb_vwv3,(uint32)size);
641 if (Protocol >= PROTOCOL_NT1)
642 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
644 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
646 END_PROFILE(SMBgetatr);
650 /****************************************************************************
652 ****************************************************************************/
654 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
661 SMB_STRUCT_STAT sbuf;
662 BOOL bad_path = False;
666 START_PROFILE(SMBsetatr);
668 p = smb_buf(inbuf) + 1;
669 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
670 if (!NT_STATUS_IS_OK(status)) {
671 END_PROFILE(SMBsetatr);
672 return ERROR_NT(status);
675 unix_convert(fname,conn,0,&bad_path,&sbuf);
677 mode = SVAL(inbuf,smb_vwv0);
678 mtime = make_unix_date3(inbuf+smb_vwv1);
680 if (mode != FILE_ATTRIBUTE_NORMAL) {
681 if (VALID_STAT_OF_DIR(sbuf))
686 if (check_name(fname,conn))
687 ok = (file_chmod(conn,fname,mode,NULL) == 0);
693 ok = set_filetime(conn,fname,mtime);
696 END_PROFILE(SMBsetatr);
697 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
700 outsize = set_message(outbuf,0,0,True);
702 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
704 END_PROFILE(SMBsetatr);
708 /****************************************************************************
710 ****************************************************************************/
712 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
715 SMB_BIG_UINT dfree,dsize,bsize;
716 START_PROFILE(SMBdskattr);
718 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
720 outsize = set_message(outbuf,5,0,True);
722 if (Protocol <= PROTOCOL_LANMAN2) {
723 double total_space, free_space;
724 /* we need to scale this to a number that DOS6 can handle. We
725 use floating point so we can handle large drives on systems
726 that don't have 64 bit integers
728 we end up displaying a maximum of 2G to DOS systems
730 total_space = dsize * (double)bsize;
731 free_space = dfree * (double)bsize;
733 dsize = (total_space+63*512) / (64*512);
734 dfree = (free_space+63*512) / (64*512);
736 if (dsize > 0xFFFF) dsize = 0xFFFF;
737 if (dfree > 0xFFFF) dfree = 0xFFFF;
739 SSVAL(outbuf,smb_vwv0,dsize);
740 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
741 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
742 SSVAL(outbuf,smb_vwv3,dfree);
744 SSVAL(outbuf,smb_vwv0,dsize);
745 SSVAL(outbuf,smb_vwv1,bsize/512);
746 SSVAL(outbuf,smb_vwv2,512);
747 SSVAL(outbuf,smb_vwv3,dfree);
750 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
752 END_PROFILE(SMBdskattr);
756 /****************************************************************************
758 Can be called from SMBsearch, SMBffirst or SMBfunique.
759 ****************************************************************************/
761 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
771 unsigned int numentries = 0;
772 unsigned int maxentries = 0;
773 BOOL finished = False;
780 BOOL check_descend = False;
781 BOOL expect_close = False;
782 BOOL can_open = True;
783 BOOL bad_path = False;
785 START_PROFILE(SMBsearch);
787 *mask = *directory = *fname = 0;
789 /* If we were called as SMBffirst then we must expect close. */
790 if(CVAL(inbuf,smb_com) == SMBffirst)
793 outsize = set_message(outbuf,1,3,True);
794 maxentries = SVAL(inbuf,smb_vwv0);
795 dirtype = SVAL(inbuf,smb_vwv1);
796 p = smb_buf(inbuf) + 1;
797 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
798 if (!NT_STATUS_IS_OK(nt_status)) {
799 END_PROFILE(SMBsearch);
800 return ERROR_NT(nt_status);
803 status_len = SVAL(p, 0);
806 /* dirtype &= ~aDIR; */
808 if (status_len == 0) {
809 SMB_STRUCT_STAT sbuf;
812 pstrcpy(directory,path);
814 unix_convert(directory,conn,0,&bad_path,&sbuf);
817 if (!check_name(directory,conn))
820 p = strrchr_m(dir2,'/');
829 p = strrchr_m(directory,'/');
835 if (strlen(directory) == 0)
836 pstrcpy(directory,".");
837 memset((char *)status,'\0',21);
838 SCVAL(status,0,(dirtype & 0x1F));
843 status_dirtype = CVAL(status,0) & 0x1F;
844 if (status_dirtype != (dirtype & 0x1F))
845 dirtype = status_dirtype;
847 conn->dirptr = dptr_fetch(status+12,&dptr_num);
850 string_set(&conn->dirpath,dptr_path(dptr_num));
851 pstrcpy(mask, dptr_wcard(dptr_num));
855 p = smb_buf(outbuf) + 3;
858 if (status_len == 0) {
859 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
862 END_PROFILE(SMBsearch);
863 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
865 END_PROFILE(SMBsearch);
866 return ERROR_DOS(ERRDOS,ERRnofids);
868 dptr_set_wcard(dptr_num, strdup(mask));
869 dptr_set_attr(dptr_num, dirtype);
871 dirtype = dptr_attr(dptr_num);
874 DEBUG(4,("dptr_num is %d\n",dptr_num));
877 if ((dirtype&0x1F) == aVOLID) {
879 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
880 dptr_fill(p+12,dptr_num);
881 if (dptr_zero(p+12) && (status_len==0))
885 p += DIR_STRUCT_SIZE;
888 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
890 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
891 conn->dirpath,lp_dontdescend(SNUM(conn))));
892 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
893 check_descend = True;
895 for (i=numentries;(i<maxentries) && !finished;i++) {
896 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
899 make_dir_struct(p,mask,fname,size,mode,date);
900 dptr_fill(p+12,dptr_num);
903 p += DIR_STRUCT_SIZE;
912 /* If we were called as SMBffirst with smb_search_id == NULL
913 and no entries were found then return error and close dirptr
916 if(ok && expect_close && numentries == 0 && status_len == 0) {
917 if (Protocol < PROTOCOL_NT1) {
918 SCVAL(outbuf,smb_rcls,ERRDOS);
919 SSVAL(outbuf,smb_err,ERRnofiles);
921 /* Also close the dptr - we know it's gone */
922 dptr_close(&dptr_num);
923 } else if (numentries == 0 || !ok) {
924 if (Protocol < PROTOCOL_NT1) {
925 SCVAL(outbuf,smb_rcls,ERRDOS);
926 SSVAL(outbuf,smb_err,ERRnofiles);
928 dptr_close(&dptr_num);
931 /* If we were called as SMBfunique, then we can close the dirptr now ! */
932 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
933 dptr_close(&dptr_num);
935 SSVAL(outbuf,smb_vwv0,numentries);
936 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
937 SCVAL(smb_buf(outbuf),0,5);
938 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
940 if (Protocol >= PROTOCOL_NT1)
941 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
943 outsize += DIR_STRUCT_SIZE*numentries;
944 smb_setlen(outbuf,outsize - 4);
946 if ((! *directory) && dptr_path(dptr_num))
947 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
949 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
950 smb_fn_name(CVAL(inbuf,smb_com)),
951 mask, directory, dirtype, numentries, maxentries ) );
953 END_PROFILE(SMBsearch);
957 /****************************************************************************
958 Reply to a fclose (stop directory search).
959 ****************************************************************************/
961 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
971 START_PROFILE(SMBfclose);
973 outsize = set_message(outbuf,1,0,True);
974 p = smb_buf(inbuf) + 1;
975 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
976 if (!NT_STATUS_IS_OK(err)) {
977 END_PROFILE(SMBfclose);
978 return ERROR_NT(err);
981 status_len = SVAL(p,0);
984 if (status_len == 0) {
985 END_PROFILE(SMBfclose);
986 return ERROR_DOS(ERRSRV,ERRsrverror);
991 if(dptr_fetch(status+12,&dptr_num)) {
992 /* Close the dptr - we know it's gone */
993 dptr_close(&dptr_num);
996 SSVAL(outbuf,smb_vwv0,0);
998 DEBUG(3,("search close\n"));
1000 END_PROFILE(SMBfclose);
1004 /****************************************************************************
1006 ****************************************************************************/
1008 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1018 SMB_STRUCT_STAT sbuf;
1019 BOOL bad_path = False;
1021 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1023 START_PROFILE(SMBopen);
1025 share_mode = SVAL(inbuf,smb_vwv0);
1027 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1028 if (!NT_STATUS_IS_OK(status)) {
1029 END_PROFILE(SMBopen);
1030 return ERROR_NT(status);
1033 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1035 unix_convert(fname,conn,0,&bad_path,&sbuf);
1037 unixmode = unix_mode(conn,aARCH,fname);
1039 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1040 unixmode, oplock_request,&rmode,NULL);
1043 END_PROFILE(SMBopen);
1044 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1047 size = sbuf.st_size;
1048 fmode = dos_mode(conn,fname,&sbuf);
1049 mtime = sbuf.st_mtime;
1052 DEBUG(3,("attempt to open a directory %s\n",fname));
1053 close_file(fsp,False);
1054 END_PROFILE(SMBopen);
1055 return ERROR_DOS(ERRDOS,ERRnoaccess);
1058 outsize = set_message(outbuf,7,0,True);
1059 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1060 SSVAL(outbuf,smb_vwv1,fmode);
1061 if(lp_dos_filetime_resolution(SNUM(conn)) )
1062 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1064 put_dos_date3(outbuf,smb_vwv2,mtime);
1065 SIVAL(outbuf,smb_vwv4,(uint32)size);
1066 SSVAL(outbuf,smb_vwv6,rmode);
1068 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1069 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1071 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1072 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1073 END_PROFILE(SMBopen);
1077 /****************************************************************************
1078 Reply to an open and X.
1079 ****************************************************************************/
1081 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1084 int smb_mode = SVAL(inbuf,smb_vwv3);
1085 int smb_attr = SVAL(inbuf,smb_vwv5);
1086 /* Breakout the oplock request bits so we can set the
1087 reply bits separately. */
1088 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1089 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1090 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1092 int open_flags = SVAL(inbuf,smb_vwv2);
1093 int smb_sattr = SVAL(inbuf,smb_vwv4);
1094 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1096 int smb_ofun = SVAL(inbuf,smb_vwv8);
1099 int fmode=0,mtime=0,rmode=0;
1100 SMB_STRUCT_STAT sbuf;
1102 BOOL bad_path = False;
1105 START_PROFILE(SMBopenX);
1107 /* If it's an IPC, pass off the pipe handler. */
1109 if (lp_nt_pipe_support()) {
1110 END_PROFILE(SMBopenX);
1111 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1113 END_PROFILE(SMBopenX);
1114 return ERROR_DOS(ERRSRV,ERRaccess);
1118 /* XXXX we need to handle passed times, sattr and flags */
1119 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 END_PROFILE(SMBopenX);
1122 return ERROR_NT(status);
1125 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1127 unix_convert(fname,conn,0,&bad_path,&sbuf);
1129 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1131 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1132 oplock_request, &rmode,&smb_action);
1135 END_PROFILE(SMBopenX);
1136 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1139 size = sbuf.st_size;
1140 fmode = dos_mode(conn,fname,&sbuf);
1141 mtime = sbuf.st_mtime;
1143 close_file(fsp,False);
1144 END_PROFILE(SMBopenX);
1145 return ERROR_DOS(ERRDOS,ERRnoaccess);
1148 /* If the caller set the extended oplock request bit
1149 and we granted one (by whatever means) - set the
1150 correct bit for extended oplock reply.
1153 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1154 smb_action |= EXTENDED_OPLOCK_GRANTED;
1156 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1157 smb_action |= EXTENDED_OPLOCK_GRANTED;
1159 /* If the caller set the core oplock request bit
1160 and we granted one (by whatever means) - set the
1161 correct bit for core oplock reply.
1164 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1165 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1167 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1168 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1170 set_message(outbuf,15,0,True);
1171 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1172 SSVAL(outbuf,smb_vwv3,fmode);
1173 if(lp_dos_filetime_resolution(SNUM(conn)) )
1174 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1176 put_dos_date3(outbuf,smb_vwv4,mtime);
1177 SIVAL(outbuf,smb_vwv6,(uint32)size);
1178 SSVAL(outbuf,smb_vwv8,rmode);
1179 SSVAL(outbuf,smb_vwv11,smb_action);
1181 END_PROFILE(SMBopenX);
1182 return chain_reply(inbuf,outbuf,length,bufsize);
1185 /****************************************************************************
1186 Reply to a SMBulogoffX.
1187 ****************************************************************************/
1189 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1191 uint16 vuid = SVAL(inbuf,smb_uid);
1192 user_struct *vuser = get_valid_user_struct(vuid);
1193 START_PROFILE(SMBulogoffX);
1196 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1198 /* in user level security we are supposed to close any files
1199 open by this user */
1200 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1201 file_close_user(vuid);
1203 invalidate_vuid(vuid);
1205 set_message(outbuf,2,0,True);
1207 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1209 END_PROFILE(SMBulogoffX);
1210 return chain_reply(inbuf,outbuf,length,bufsize);
1213 /****************************************************************************
1214 Reply to a mknew or a create.
1215 ****************************************************************************/
1217 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1225 BOOL bad_path = False;
1227 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1228 SMB_STRUCT_STAT sbuf;
1230 START_PROFILE(SMBcreate);
1232 com = SVAL(inbuf,smb_com);
1234 createmode = SVAL(inbuf,smb_vwv0);
1235 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1236 if (!NT_STATUS_IS_OK(status)) {
1237 END_PROFILE(SMBcreate);
1238 return ERROR_NT(status);
1241 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1243 unix_convert(fname,conn,0,&bad_path,&sbuf);
1245 if (createmode & aVOLID)
1246 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1248 unixmode = unix_mode(conn,createmode,fname);
1250 if(com == SMBmknew) {
1251 /* We should fail if file exists. */
1252 ofun = FILE_CREATE_IF_NOT_EXIST;
1254 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1255 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1258 /* Open file in dos compatibility share mode. */
1259 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1260 ofun, unixmode, oplock_request, NULL, NULL);
1263 END_PROFILE(SMBcreate);
1264 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1267 outsize = set_message(outbuf,1,0,True);
1268 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1270 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1271 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1273 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1274 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1276 DEBUG( 2, ( "new file %s\n", fname ) );
1277 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1279 END_PROFILE(SMBcreate);
1283 /****************************************************************************
1284 Reply to a create temporary file.
1285 ****************************************************************************/
1287 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1293 BOOL bad_path = False;
1295 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1297 SMB_STRUCT_STAT sbuf;
1301 START_PROFILE(SMBctemp);
1303 createmode = SVAL(inbuf,smb_vwv0);
1304 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1305 if (!NT_STATUS_IS_OK(status)) {
1306 END_PROFILE(SMBctemp);
1307 return ERROR_NT(status);
1309 pstrcat(fname,"\\TMXXXXXX");
1311 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1313 unix_convert(fname,conn,0,&bad_path,&sbuf);
1315 unixmode = unix_mode(conn,createmode,fname);
1317 tmpfd = smb_mkstemp(fname);
1319 END_PROFILE(SMBctemp);
1320 return(UNIXERROR(ERRDOS,ERRnoaccess));
1323 SMB_VFS_STAT(conn,fname,&sbuf);
1325 /* Open file in dos compatibility share mode. */
1326 /* We should fail if file does not exist. */
1327 fsp = open_file_shared(conn,fname,&sbuf,
1328 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1329 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1330 unixmode, oplock_request, NULL, NULL);
1332 /* close fd from smb_mkstemp() */
1336 END_PROFILE(SMBctemp);
1337 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1340 outsize = set_message(outbuf,1,0,True);
1341 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1343 /* the returned filename is relative to the directory */
1344 s = strrchr_m(fname, '/');
1350 p = smb_buf(outbuf);
1351 SSVALS(p, 0, -1); /* what is this? not in spec */
1352 SSVAL(p, 2, strlen(s));
1354 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1355 outsize = set_message_end(outbuf, p);
1357 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1358 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1360 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1361 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1363 DEBUG( 2, ( "created temp file %s\n", fname ) );
1364 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1365 fname, fsp->fd, createmode, (int)unixmode ) );
1367 END_PROFILE(SMBctemp);
1371 /*******************************************************************
1372 Check if a user is allowed to rename a file.
1373 ********************************************************************/
1375 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1381 if (!CAN_WRITE(conn))
1382 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1384 if (S_ISDIR(pst->st_mode))
1385 return NT_STATUS_OK;
1387 /* We need a better way to return NT status codes from open... */
1391 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1392 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1395 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1396 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1397 ret = NT_STATUS_SHARING_VIOLATION;
1400 unix_ERR_ntstatus = NT_STATUS_OK;
1403 close_file(fsp,False);
1404 return NT_STATUS_OK;
1407 /*******************************************************************
1408 Check if a user is allowed to delete a file.
1409 ********************************************************************/
1411 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1413 SMB_STRUCT_STAT sbuf;
1419 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1422 if (!CAN_WRITE(conn))
1423 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1425 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1426 if(errno == ENOENT) {
1428 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1430 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1432 return map_nt_error_from_unix(errno);
1435 fmode = dos_mode(conn,fname,&sbuf);
1437 /* Can't delete a directory. */
1439 return NT_STATUS_FILE_IS_A_DIRECTORY;
1441 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1442 return NT_STATUS_OBJECT_NAME_INVALID;
1443 #endif /* JRATEST */
1445 if (!lp_delete_readonly(SNUM(conn))) {
1447 return NT_STATUS_CANNOT_DELETE;
1449 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1450 return NT_STATUS_NO_SUCH_FILE;
1452 /* We need a better way to return NT status codes from open... */
1456 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1457 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1460 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1461 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1462 ret = unix_ERR_ntstatus;
1463 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1464 ret = NT_STATUS_SHARING_VIOLATION;
1467 unix_ERR_ntstatus = NT_STATUS_OK;
1470 close_file(fsp,False);
1471 return NT_STATUS_OK;
1474 /****************************************************************************
1475 The guts of the unlink command, split out so it may be called by the NT SMB
1477 ****************************************************************************/
1479 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1485 NTSTATUS error = NT_STATUS_OK;
1487 BOOL bad_path = False;
1489 SMB_STRUCT_STAT sbuf;
1491 *directory = *mask = 0;
1493 /* We must check for wildcards in the name given
1494 * directly by the client - before any unmangling.
1495 * This prevents an unmangling of a UNIX name containing
1496 * a DOS wildcard like '*' or '?' from unmangling into
1497 * a wildcard delete which was not intended.
1498 * FIX for #226. JRA.
1501 has_wild = ms_has_wild(name);
1503 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1505 p = strrchr_m(name,'/');
1507 pstrcpy(directory,".");
1511 pstrcpy(directory,name);
1516 * We should only check the mangled cache
1517 * here if unix_convert failed. This means
1518 * that the path in 'mask' doesn't exist
1519 * on the file system and so we need to look
1520 * for a possible mangle. This patch from
1521 * Tine Smukavec <valentin.smukavec@hermes.si>.
1524 if (!rc && mangle_is_mangled(mask))
1525 mangle_check_cache( mask );
1528 pstrcat(directory,"/");
1529 pstrcat(directory,mask);
1530 error = can_delete(directory,conn,dirtype,bad_path);
1531 if (!NT_STATUS_IS_OK(error))
1534 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1538 void *dirptr = NULL;
1541 if (check_name(directory,conn))
1542 dirptr = OpenDir(conn, directory, True);
1544 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1545 the pattern matches against the long name, otherwise the short name
1546 We don't implement this yet XXXX
1550 error = NT_STATUS_NO_SUCH_FILE;
1552 if (strequal(mask,"????????.???"))
1555 while ((dname = ReadDirName(dirptr))) {
1557 BOOL sys_direntry = False;
1558 pstrcpy(fname,dname);
1560 /* Quick check for "." and ".." */
1561 if (fname[0] == '.') {
1562 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1563 if ((dirtype & aDIR)) {
1564 sys_direntry = True;
1571 if(!mask_match(fname, mask, case_sensitive))
1575 error = NT_STATUS_OBJECT_NAME_INVALID;
1579 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1580 error = can_delete(fname,conn,dirtype,bad_path);
1581 if (!NT_STATUS_IS_OK(error))
1583 if (SMB_VFS_UNLINK(conn,fname) == 0)
1585 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1591 if (count == 0 && NT_STATUS_IS_OK(error)) {
1592 error = map_nt_error_from_unix(errno);
1598 /****************************************************************************
1600 ****************************************************************************/
1602 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1609 START_PROFILE(SMBunlink);
1611 dirtype = SVAL(inbuf,smb_vwv0);
1613 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 END_PROFILE(SMBunlink);
1616 return ERROR_NT(status);
1619 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1621 DEBUG(3,("reply_unlink : %s\n",name));
1623 status = unlink_internals(conn, dirtype, name);
1624 if (!NT_STATUS_IS_OK(status))
1625 return ERROR_NT(status);
1628 * Win2k needs a changenotify request response before it will
1629 * update after a rename..
1631 process_pending_change_notify_queue((time_t)0);
1633 outsize = set_message(outbuf,0,0,True);
1635 END_PROFILE(SMBunlink);
1639 /****************************************************************************
1641 ****************************************************************************/
1643 void fail_readraw(void)
1646 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1648 exit_server(errstr);
1651 /****************************************************************************
1652 Use sendfile in readbraw.
1653 ****************************************************************************/
1655 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1656 ssize_t mincount, char *outbuf)
1660 #if defined(WITH_SENDFILE)
1662 * We can only use sendfile on a non-chained packet and on a file
1663 * that is exclusively oplocked. reply_readbraw has already checked the length.
1666 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1667 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1670 _smb_setlen(outbuf,nread);
1671 header.data = outbuf;
1675 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1677 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1678 * return ENOSYS then pretend we just got a normal read.
1680 if (errno == ENOSYS)
1683 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1684 fsp->fsp_name, strerror(errno) ));
1685 exit_server("send_file_readbraw sendfile failed");
1694 ret = read_file(fsp,outbuf+4,startpos,nread);
1695 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1704 _smb_setlen(outbuf,ret);
1705 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1709 /****************************************************************************
1710 Reply to a readbraw (core+ protocol).
1711 ****************************************************************************/
1713 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1715 extern struct current_user current_user;
1716 ssize_t maxcount,mincount;
1719 char *header = outbuf;
1721 START_PROFILE(SMBreadbraw);
1723 if (srv_is_signing_active()) {
1724 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1728 * Special check if an oplock break has been issued
1729 * and the readraw request croses on the wire, we must
1730 * return a zero length response here.
1733 if(global_oplock_break) {
1734 _smb_setlen(header,0);
1735 if (write_data(smbd_server_fd(),header,4) != 4)
1737 DEBUG(5,("readbraw - oplock break finished\n"));
1738 END_PROFILE(SMBreadbraw);
1742 fsp = file_fsp(inbuf,smb_vwv0);
1744 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1746 * fsp could be NULL here so use the value from the packet. JRA.
1748 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1749 _smb_setlen(header,0);
1750 if (write_data(smbd_server_fd(),header,4) != 4)
1752 END_PROFILE(SMBreadbraw);
1756 CHECK_FSP(fsp,conn);
1758 flush_write_cache(fsp, READRAW_FLUSH);
1760 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1761 if(CVAL(inbuf,smb_wct) == 10) {
1763 * This is a large offset (64 bit) read.
1765 #ifdef LARGE_SMB_OFF_T
1767 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1769 #else /* !LARGE_SMB_OFF_T */
1772 * Ensure we haven't been sent a >32 bit offset.
1775 if(IVAL(inbuf,smb_vwv8) != 0) {
1776 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1777 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1778 _smb_setlen(header,0);
1779 if (write_data(smbd_server_fd(),header,4) != 4)
1781 END_PROFILE(SMBreadbraw);
1785 #endif /* LARGE_SMB_OFF_T */
1788 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1789 _smb_setlen(header,0);
1790 if (write_data(smbd_server_fd(),header,4) != 4)
1792 END_PROFILE(SMBreadbraw);
1796 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1797 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1799 /* ensure we don't overrun the packet size */
1800 maxcount = MIN(65535,maxcount);
1802 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1803 SMB_OFF_T size = fsp->size;
1804 SMB_OFF_T sizeneeded = startpos + maxcount;
1806 if (size < sizeneeded) {
1808 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1810 if (!fsp->can_write)
1814 if (startpos >= size)
1817 nread = MIN(maxcount,(size - startpos));
1820 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1821 if (nread < mincount)
1825 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1826 (int)maxcount, (int)mincount, (int)nread ) );
1828 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1830 DEBUG(5,("readbraw finished\n"));
1831 END_PROFILE(SMBreadbraw);
1835 /****************************************************************************
1836 Reply to a lockread (core+ protocol).
1837 ****************************************************************************/
1839 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1847 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1848 BOOL my_lock_ctx = False;
1849 START_PROFILE(SMBlockread);
1851 CHECK_FSP(fsp,conn);
1854 release_level_2_oplocks_on_change(fsp);
1856 numtoread = SVAL(inbuf,smb_vwv1);
1857 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1859 outsize = set_message(outbuf,5,3,True);
1860 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1861 data = smb_buf(outbuf) + 3;
1864 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1865 * protocol request that predates the read/write lock concept.
1866 * Thus instead of asking for a read lock here we need to ask
1867 * for a write lock. JRA.
1868 * Note that the requested lock size is unaffected by max_recv.
1871 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1872 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1874 if (NT_STATUS_V(status)) {
1877 * We used to make lockread a blocking lock. It turns out
1878 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1882 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1884 * A blocking lock was requested. Package up
1885 * this smb into a queued request and push it
1886 * onto the blocking lock queue.
1888 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1889 (SMB_BIG_UINT)numtoread)) {
1890 END_PROFILE(SMBlockread);
1895 END_PROFILE(SMBlockread);
1896 return ERROR_NT(status);
1900 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1903 if (numtoread > max_recv) {
1904 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1905 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1906 (unsigned int)numtoread, (unsigned int)max_recv ));
1907 numtoread = MIN(numtoread,max_recv);
1909 nread = read_file(fsp,data,startpos,numtoread);
1912 END_PROFILE(SMBlockread);
1913 return(UNIXERROR(ERRDOS,ERRnoaccess));
1917 SSVAL(outbuf,smb_vwv0,nread);
1918 SSVAL(outbuf,smb_vwv5,nread+3);
1919 SSVAL(smb_buf(outbuf),1,nread);
1921 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1922 fsp->fnum, (int)numtoread, (int)nread));
1924 END_PROFILE(SMBlockread);
1928 /****************************************************************************
1930 ****************************************************************************/
1932 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1939 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1940 START_PROFILE(SMBread);
1942 CHECK_FSP(fsp,conn);
1945 numtoread = SVAL(inbuf,smb_vwv1);
1946 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1948 outsize = set_message(outbuf,5,3,True);
1949 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1951 * The requested read size cannot be greater than max_recv. JRA.
1953 if (numtoread > max_recv) {
1954 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1955 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1956 (unsigned int)numtoread, (unsigned int)max_recv ));
1957 numtoread = MIN(numtoread,max_recv);
1960 data = smb_buf(outbuf) + 3;
1962 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1963 END_PROFILE(SMBread);
1964 return ERROR_DOS(ERRDOS,ERRlock);
1968 nread = read_file(fsp,data,startpos,numtoread);
1971 END_PROFILE(SMBread);
1972 return(UNIXERROR(ERRDOS,ERRnoaccess));
1976 SSVAL(outbuf,smb_vwv0,nread);
1977 SSVAL(outbuf,smb_vwv5,nread+3);
1978 SCVAL(smb_buf(outbuf),0,1);
1979 SSVAL(smb_buf(outbuf),1,nread);
1981 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1982 fsp->fnum, (int)numtoread, (int)nread ) );
1984 END_PROFILE(SMBread);
1988 /****************************************************************************
1989 Reply to a read and X - possibly using sendfile.
1990 ****************************************************************************/
1992 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1993 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1996 char *data = smb_buf(outbuf);
1998 #if defined(WITH_SENDFILE)
2000 * We can only use sendfile on a non-chained packet and on a file
2001 * that is exclusively oplocked.
2004 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2005 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2006 SMB_STRUCT_STAT sbuf;
2009 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2010 return(UNIXERROR(ERRDOS,ERRnoaccess));
2012 if (startpos > sbuf.st_size)
2015 if (smb_maxcnt > (sbuf.st_size - startpos))
2016 smb_maxcnt = (sbuf.st_size - startpos);
2018 if (smb_maxcnt == 0)
2022 * Set up the packet header before send. We
2023 * assume here the sendfile will work (get the
2024 * correct amount of data).
2027 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2028 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2029 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2030 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2031 SCVAL(outbuf,smb_vwv0,0xFF);
2032 set_message(outbuf,12,smb_maxcnt,False);
2033 header.data = outbuf;
2034 header.length = data - outbuf;
2037 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2039 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2040 * return ENOSYS then pretend we just got a normal read.
2042 if (errno == ENOSYS)
2045 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2046 fsp->fsp_name, strerror(errno) ));
2047 exit_server("send_file_readX sendfile failed");
2050 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2051 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2059 nread = read_file(fsp,data,startpos,smb_maxcnt);
2062 END_PROFILE(SMBreadX);
2063 return(UNIXERROR(ERRDOS,ERRnoaccess));
2066 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2067 SSVAL(outbuf,smb_vwv5,nread);
2068 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2069 SSVAL(smb_buf(outbuf),-2,nread);
2071 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2072 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2077 /****************************************************************************
2078 Reply to a read and X.
2079 ****************************************************************************/
2081 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2083 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2084 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2086 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2088 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2091 START_PROFILE(SMBreadX);
2093 /* If it's an IPC, pass off the pipe handler. */
2095 END_PROFILE(SMBreadX);
2096 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2099 CHECK_FSP(fsp,conn);
2102 set_message(outbuf,12,0,True);
2104 if(CVAL(inbuf,smb_wct) == 12) {
2105 #ifdef LARGE_SMB_OFF_T
2107 * This is a large offset (64 bit) read.
2109 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2111 #else /* !LARGE_SMB_OFF_T */
2114 * Ensure we haven't been sent a >32 bit offset.
2117 if(IVAL(inbuf,smb_vwv10) != 0) {
2118 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2119 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2120 END_PROFILE(SMBreadX);
2121 return ERROR_DOS(ERRDOS,ERRbadaccess);
2124 #endif /* LARGE_SMB_OFF_T */
2128 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2129 END_PROFILE(SMBreadX);
2130 return ERROR_DOS(ERRDOS,ERRlock);
2133 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2135 nread = chain_reply(inbuf,outbuf,length,bufsize);
2137 END_PROFILE(SMBreadX);
2141 /****************************************************************************
2142 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2143 ****************************************************************************/
2145 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2148 ssize_t total_written=0;
2149 size_t numtowrite=0;
2154 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2156 START_PROFILE(SMBwritebraw);
2158 if (srv_is_signing_active()) {
2159 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2162 CHECK_FSP(fsp,conn);
2165 tcount = IVAL(inbuf,smb_vwv1);
2166 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2167 write_through = BITSETW(inbuf+smb_vwv7,0);
2169 /* We have to deal with slightly different formats depending
2170 on whether we are using the core+ or lanman1.0 protocol */
2172 if(Protocol <= PROTOCOL_COREPLUS) {
2173 numtowrite = SVAL(smb_buf(inbuf),-2);
2174 data = smb_buf(inbuf);
2176 numtowrite = SVAL(inbuf,smb_vwv10);
2177 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2180 /* force the error type */
2181 SCVAL(inbuf,smb_com,SMBwritec);
2182 SCVAL(outbuf,smb_com,SMBwritec);
2184 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2185 END_PROFILE(SMBwritebraw);
2186 return(ERROR_DOS(ERRDOS,ERRlock));
2190 nwritten = write_file(fsp,data,startpos,numtowrite);
2192 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2193 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2195 if (nwritten < (ssize_t)numtowrite) {
2196 END_PROFILE(SMBwritebraw);
2197 return(UNIXERROR(ERRHRD,ERRdiskfull));
2200 total_written = nwritten;
2202 /* Return a message to the redirector to tell it to send more bytes */
2203 SCVAL(outbuf,smb_com,SMBwritebraw);
2204 SSVALS(outbuf,smb_vwv0,-1);
2205 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2206 if (!send_smb(smbd_server_fd(),outbuf))
2207 exit_server("reply_writebraw: send_smb failed.");
2209 /* Now read the raw data into the buffer and write it */
2210 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2211 exit_server("secondary writebraw failed");
2214 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2215 numtowrite = smb_len(inbuf);
2217 /* Set up outbuf to return the correct return */
2218 outsize = set_message(outbuf,1,0,True);
2219 SCVAL(outbuf,smb_com,SMBwritec);
2220 SSVAL(outbuf,smb_vwv0,total_written);
2222 if (numtowrite != 0) {
2224 if (numtowrite > BUFFER_SIZE) {
2225 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2226 (unsigned int)numtowrite ));
2227 exit_server("secondary writebraw failed");
2230 if (tcount > nwritten+numtowrite) {
2231 DEBUG(3,("Client overestimated the write %d %d %d\n",
2232 (int)tcount,(int)nwritten,(int)numtowrite));
2235 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2236 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2238 exit_server("secondary writebraw failed");
2241 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2243 if (nwritten < (ssize_t)numtowrite) {
2244 SCVAL(outbuf,smb_rcls,ERRHRD);
2245 SSVAL(outbuf,smb_err,ERRdiskfull);
2249 total_written += nwritten;
2252 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2253 sync_file(conn,fsp);
2255 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2256 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2258 /* we won't return a status if write through is not selected - this follows what WfWg does */
2259 END_PROFILE(SMBwritebraw);
2260 if (!write_through && total_written==tcount) {
2262 #if RABBIT_PELLET_FIX
2264 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2265 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2267 if (!send_keepalive(smbd_server_fd()))
2268 exit_server("reply_writebraw: send of keepalive failed");
2276 /****************************************************************************
2277 Reply to a writeunlock (core+).
2278 ****************************************************************************/
2280 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2281 int size, int dum_buffsize)
2283 ssize_t nwritten = -1;
2287 NTSTATUS status = NT_STATUS_OK;
2288 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2290 START_PROFILE(SMBwriteunlock);
2292 CHECK_FSP(fsp,conn);
2295 numtowrite = SVAL(inbuf,smb_vwv1);
2296 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2297 data = smb_buf(inbuf) + 3;
2299 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2300 WRITE_LOCK,False)) {
2301 END_PROFILE(SMBwriteunlock);
2302 return ERROR_DOS(ERRDOS,ERRlock);
2305 /* The special X/Open SMB protocol handling of
2306 zero length writes is *NOT* done for
2311 nwritten = write_file(fsp,data,startpos,numtowrite);
2313 if (lp_syncalways(SNUM(conn)))
2314 sync_file(conn,fsp);
2316 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2317 END_PROFILE(SMBwriteunlock);
2318 return(UNIXERROR(ERRHRD,ERRdiskfull));
2322 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2323 (SMB_BIG_UINT)startpos);
2324 if (NT_STATUS_V(status)) {
2325 END_PROFILE(SMBwriteunlock);
2326 return ERROR_NT(status);
2330 outsize = set_message(outbuf,1,0,True);
2332 SSVAL(outbuf,smb_vwv0,nwritten);
2334 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2335 fsp->fnum, (int)numtowrite, (int)nwritten));
2337 END_PROFILE(SMBwriteunlock);
2341 /****************************************************************************
2343 ****************************************************************************/
2345 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2348 ssize_t nwritten = -1;
2351 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2353 START_PROFILE(SMBwrite);
2355 /* If it's an IPC, pass off the pipe handler. */
2357 END_PROFILE(SMBwrite);
2358 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2361 CHECK_FSP(fsp,conn);
2364 numtowrite = SVAL(inbuf,smb_vwv1);
2365 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2366 data = smb_buf(inbuf) + 3;
2368 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2369 END_PROFILE(SMBwrite);
2370 return ERROR_DOS(ERRDOS,ERRlock);
2374 * X/Open SMB protocol says that if smb_vwv1 is
2375 * zero then the file size should be extended or
2376 * truncated to the size given in smb_vwv[2-3].
2379 if(numtowrite == 0) {
2381 * This is actually an allocate call, and set EOF. JRA.
2383 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2385 END_PROFILE(SMBwrite);
2386 return ERROR_NT(NT_STATUS_DISK_FULL);
2388 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2390 END_PROFILE(SMBwrite);
2391 return ERROR_NT(NT_STATUS_DISK_FULL);
2394 nwritten = write_file(fsp,data,startpos,numtowrite);
2396 if (lp_syncalways(SNUM(conn)))
2397 sync_file(conn,fsp);
2399 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2400 END_PROFILE(SMBwrite);
2401 return(UNIXERROR(ERRHRD,ERRdiskfull));
2404 outsize = set_message(outbuf,1,0,True);
2406 SSVAL(outbuf,smb_vwv0,nwritten);
2408 if (nwritten < (ssize_t)numtowrite) {
2409 SCVAL(outbuf,smb_rcls,ERRHRD);
2410 SSVAL(outbuf,smb_err,ERRdiskfull);
2413 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2415 END_PROFILE(SMBwrite);
2419 /****************************************************************************
2420 Reply to a write and X.
2421 ****************************************************************************/
2423 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2425 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2426 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2427 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2428 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2429 ssize_t nwritten = -1;
2430 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2431 unsigned int smblen = smb_len(inbuf);
2433 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2434 START_PROFILE(SMBwriteX);
2436 /* If it's an IPC, pass off the pipe handler. */
2438 END_PROFILE(SMBwriteX);
2439 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2442 CHECK_FSP(fsp,conn);
2445 /* Deal with possible LARGE_WRITEX */
2447 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2449 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2450 END_PROFILE(SMBwriteX);
2451 return ERROR_DOS(ERRDOS,ERRbadmem);
2454 data = smb_base(inbuf) + smb_doff;
2456 if(CVAL(inbuf,smb_wct) == 14) {
2457 #ifdef LARGE_SMB_OFF_T
2459 * This is a large offset (64 bit) write.
2461 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2463 #else /* !LARGE_SMB_OFF_T */
2466 * Ensure we haven't been sent a >32 bit offset.
2469 if(IVAL(inbuf,smb_vwv12) != 0) {
2470 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2471 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2472 END_PROFILE(SMBwriteX);
2473 return ERROR_DOS(ERRDOS,ERRbadaccess);
2476 #endif /* LARGE_SMB_OFF_T */
2479 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2480 END_PROFILE(SMBwriteX);
2481 return ERROR_DOS(ERRDOS,ERRlock);
2484 /* X/Open SMB protocol says that, unlike SMBwrite
2485 if the length is zero then NO truncation is
2486 done, just a write of zero. To truncate a file,
2492 nwritten = write_file(fsp,data,startpos,numtowrite);
2494 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2495 END_PROFILE(SMBwriteX);
2496 return(UNIXERROR(ERRHRD,ERRdiskfull));
2499 set_message(outbuf,6,0,True);
2501 SSVAL(outbuf,smb_vwv2,nwritten);
2503 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2505 if (nwritten < (ssize_t)numtowrite) {
2506 SCVAL(outbuf,smb_rcls,ERRHRD);
2507 SSVAL(outbuf,smb_err,ERRdiskfull);
2510 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2511 fsp->fnum, (int)numtowrite, (int)nwritten));
2513 if (lp_syncalways(SNUM(conn)) || write_through)
2514 sync_file(conn,fsp);
2516 END_PROFILE(SMBwriteX);
2517 return chain_reply(inbuf,outbuf,length,bufsize);
2520 /****************************************************************************
2522 ****************************************************************************/
2524 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2530 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2531 START_PROFILE(SMBlseek);
2533 CHECK_FSP(fsp,conn);
2535 flush_write_cache(fsp, SEEK_FLUSH);
2537 mode = SVAL(inbuf,smb_vwv1) & 3;
2538 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2539 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2548 res = fsp->pos + startpos;
2559 if (umode == SEEK_END) {
2560 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2561 if(errno == EINVAL) {
2562 SMB_OFF_T current_pos = startpos;
2563 SMB_STRUCT_STAT sbuf;
2565 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2566 END_PROFILE(SMBlseek);
2567 return(UNIXERROR(ERRDOS,ERRnoaccess));
2570 current_pos += sbuf.st_size;
2572 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2577 END_PROFILE(SMBlseek);
2578 return(UNIXERROR(ERRDOS,ERRnoaccess));
2584 outsize = set_message(outbuf,2,0,True);
2585 SIVAL(outbuf,smb_vwv0,res);
2587 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2588 fsp->fnum, (double)startpos, (double)res, mode));
2590 END_PROFILE(SMBlseek);
2594 /****************************************************************************
2596 ****************************************************************************/
2598 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2600 int outsize = set_message(outbuf,0,0,True);
2601 uint16 fnum = SVAL(inbuf,smb_vwv0);
2602 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2603 START_PROFILE(SMBflush);
2606 CHECK_FSP(fsp,conn);
2609 file_sync_all(conn);
2611 sync_file(conn,fsp);
2614 DEBUG(3,("flush\n"));
2615 END_PROFILE(SMBflush);
2619 /****************************************************************************
2621 ****************************************************************************/
2623 int reply_exit(connection_struct *conn,
2624 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2627 START_PROFILE(SMBexit);
2629 file_close_pid(SVAL(inbuf,smb_pid));
2631 outsize = set_message(outbuf,0,0,True);
2633 DEBUG(3,("exit\n"));
2635 END_PROFILE(SMBexit);
2639 /****************************************************************************
2640 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2641 ****************************************************************************/
2643 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2646 extern struct current_user current_user;
2649 int32 eclass = 0, err = 0;
2650 files_struct *fsp = NULL;
2651 START_PROFILE(SMBclose);
2653 outsize = set_message(outbuf,0,0,True);
2655 /* If it's an IPC, pass off to the pipe handler. */
2657 END_PROFILE(SMBclose);
2658 return reply_pipe_close(conn, inbuf,outbuf);
2661 fsp = file_fsp(inbuf,smb_vwv0);
2664 * We can only use CHECK_FSP if we know it's not a directory.
2667 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2668 END_PROFILE(SMBclose);
2669 return ERROR_DOS(ERRDOS,ERRbadfid);
2672 if(fsp->is_directory) {
2674 * Special case - close NT SMB directory handle.
2676 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2677 close_file(fsp,True);
2680 * Close ordinary file.
2685 /* Save the name for time set in close. */
2686 pstrcpy( file_name, fsp->fsp_name);
2688 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2690 conn->num_files_open));
2693 * close_file() returns the unix errno if an error
2694 * was detected on close - normally this is due to
2695 * a disk full error. If not then it was probably an I/O error.
2698 if((close_err = close_file(fsp,True)) != 0) {
2700 END_PROFILE(SMBclose);
2701 return (UNIXERROR(ERRHRD,ERRgeneral));
2705 * Now take care of any time sent in the close.
2708 mtime = make_unix_date3(inbuf+smb_vwv1);
2710 /* try and set the date */
2711 set_filetime(conn, file_name, mtime);
2715 /* We have a cached error */
2717 END_PROFILE(SMBclose);
2718 return ERROR_DOS(eclass,err);
2721 END_PROFILE(SMBclose);
2725 /****************************************************************************
2726 Reply to a writeclose (Core+ protocol).
2727 ****************************************************************************/
2729 int reply_writeclose(connection_struct *conn,
2730 char *inbuf,char *outbuf, int size, int dum_buffsize)
2733 ssize_t nwritten = -1;
2739 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2740 START_PROFILE(SMBwriteclose);
2742 CHECK_FSP(fsp,conn);
2745 numtowrite = SVAL(inbuf,smb_vwv1);
2746 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2747 mtime = make_unix_date3(inbuf+smb_vwv4);
2748 data = smb_buf(inbuf) + 1;
2750 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2751 END_PROFILE(SMBwriteclose);
2752 return ERROR_DOS(ERRDOS,ERRlock);
2755 nwritten = write_file(fsp,data,startpos,numtowrite);
2757 set_filetime(conn, fsp->fsp_name,mtime);
2760 * More insanity. W2K only closes the file if writelen > 0.
2765 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2767 close_err = close_file(fsp,True);
2770 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2771 fsp->fnum, (int)numtowrite, (int)nwritten,
2772 conn->num_files_open));
2774 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2775 END_PROFILE(SMBwriteclose);
2776 return(UNIXERROR(ERRHRD,ERRdiskfull));
2779 if(close_err != 0) {
2781 END_PROFILE(SMBwriteclose);
2782 return(UNIXERROR(ERRHRD,ERRgeneral));
2785 outsize = set_message(outbuf,1,0,True);
2787 SSVAL(outbuf,smb_vwv0,nwritten);
2788 END_PROFILE(SMBwriteclose);
2792 /****************************************************************************
2794 ****************************************************************************/
2796 int reply_lock(connection_struct *conn,
2797 char *inbuf,char *outbuf, int length, int dum_buffsize)
2799 int outsize = set_message(outbuf,0,0,True);
2800 SMB_BIG_UINT count,offset;
2802 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2803 BOOL my_lock_ctx = False;
2805 START_PROFILE(SMBlock);
2807 CHECK_FSP(fsp,conn);
2809 release_level_2_oplocks_on_change(fsp);
2811 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2812 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2814 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2815 fsp->fd, fsp->fnum, (double)offset, (double)count));
2817 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2818 if (NT_STATUS_V(status)) {
2820 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2821 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2823 * A blocking lock was requested. Package up
2824 * this smb into a queued request and push it
2825 * onto the blocking lock queue.
2827 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2828 END_PROFILE(SMBlock);
2833 END_PROFILE(SMBlock);
2834 return ERROR_NT(status);
2837 END_PROFILE(SMBlock);
2841 /****************************************************************************
2843 ****************************************************************************/
2845 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2848 int outsize = set_message(outbuf,0,0,True);
2849 SMB_BIG_UINT count,offset;
2851 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2852 START_PROFILE(SMBunlock);
2854 CHECK_FSP(fsp,conn);
2856 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2857 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2859 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2860 if (NT_STATUS_V(status)) {
2861 END_PROFILE(SMBunlock);
2862 return ERROR_NT(status);
2865 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2866 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2868 END_PROFILE(SMBunlock);
2872 /****************************************************************************
2874 ****************************************************************************/
2876 int reply_tdis(connection_struct *conn,
2877 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2879 int outsize = set_message(outbuf,0,0,True);
2881 START_PROFILE(SMBtdis);
2883 vuid = SVAL(inbuf,smb_uid);
2886 DEBUG(4,("Invalid connection in tdis\n"));
2887 END_PROFILE(SMBtdis);
2888 return ERROR_DOS(ERRSRV,ERRinvnid);
2893 close_cnum(conn,vuid);
2895 END_PROFILE(SMBtdis);
2899 /****************************************************************************
2901 ****************************************************************************/
2903 int reply_echo(connection_struct *conn,
2904 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2906 int smb_reverb = SVAL(inbuf,smb_vwv0);
2908 unsigned int data_len = smb_buflen(inbuf);
2909 int outsize = set_message(outbuf,1,data_len,True);
2910 START_PROFILE(SMBecho);
2912 if (data_len > BUFFER_SIZE) {
2913 DEBUG(0,("reply_echo: data_len too large.\n"));
2914 END_PROFILE(SMBecho);
2918 /* copy any incoming data back out */
2920 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2922 if (smb_reverb > 100) {
2923 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2927 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2928 SSVAL(outbuf,smb_vwv0,seq_num);
2930 smb_setlen(outbuf,outsize - 4);
2932 if (!send_smb(smbd_server_fd(),outbuf))
2933 exit_server("reply_echo: send_smb failed.");
2936 DEBUG(3,("echo %d times\n", smb_reverb));
2940 END_PROFILE(SMBecho);
2944 /****************************************************************************
2945 Reply to a printopen.
2946 ****************************************************************************/
2948 int reply_printopen(connection_struct *conn,
2949 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2953 START_PROFILE(SMBsplopen);
2955 if (!CAN_PRINT(conn)) {
2956 END_PROFILE(SMBsplopen);
2957 return ERROR_DOS(ERRDOS,ERRnoaccess);
2960 /* Open for exclusive use, write only. */
2961 fsp = print_fsp_open(conn, NULL);
2964 END_PROFILE(SMBsplopen);
2965 return(UNIXERROR(ERRDOS,ERRnoaccess));
2968 outsize = set_message(outbuf,1,0,True);
2969 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2971 DEBUG(3,("openprint fd=%d fnum=%d\n",
2972 fsp->fd, fsp->fnum));
2974 END_PROFILE(SMBsplopen);
2978 /****************************************************************************
2979 Reply to a printclose.
2980 ****************************************************************************/
2982 int reply_printclose(connection_struct *conn,
2983 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2985 int outsize = set_message(outbuf,0,0,True);
2986 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2988 START_PROFILE(SMBsplclose);
2990 CHECK_FSP(fsp,conn);
2992 if (!CAN_PRINT(conn)) {
2993 END_PROFILE(SMBsplclose);
2994 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2997 DEBUG(3,("printclose fd=%d fnum=%d\n",
2998 fsp->fd,fsp->fnum));
3000 close_err = close_file(fsp,True);
3002 if(close_err != 0) {
3004 END_PROFILE(SMBsplclose);
3005 return(UNIXERROR(ERRHRD,ERRgeneral));
3008 END_PROFILE(SMBsplclose);
3012 /****************************************************************************
3013 Reply to a printqueue.
3014 ****************************************************************************/
3016 int reply_printqueue(connection_struct *conn,
3017 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3019 int outsize = set_message(outbuf,2,3,True);
3020 int max_count = SVAL(inbuf,smb_vwv0);
3021 int start_index = SVAL(inbuf,smb_vwv1);
3022 START_PROFILE(SMBsplretq);
3024 /* we used to allow the client to get the cnum wrong, but that
3025 is really quite gross and only worked when there was only
3026 one printer - I think we should now only accept it if they
3027 get it right (tridge) */
3028 if (!CAN_PRINT(conn)) {
3029 END_PROFILE(SMBsplretq);
3030 return ERROR_DOS(ERRDOS,ERRnoaccess);
3033 SSVAL(outbuf,smb_vwv0,0);
3034 SSVAL(outbuf,smb_vwv1,0);
3035 SCVAL(smb_buf(outbuf),0,1);
3036 SSVAL(smb_buf(outbuf),1,0);
3038 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3039 start_index, max_count));
3042 print_queue_struct *queue = NULL;
3043 print_status_struct status;
3044 char *p = smb_buf(outbuf) + 3;
3045 int count = print_queue_status(SNUM(conn), &queue, &status);
3046 int num_to_get = ABS(max_count);
3047 int first = (max_count>0?start_index:start_index+max_count+1);
3053 num_to_get = MIN(num_to_get,count-first);
3056 for (i=first;i<first+num_to_get;i++) {
3057 put_dos_date2(p,0,queue[i].time);
3058 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3059 SSVAL(p,5, queue[i].job);
3060 SIVAL(p,7,queue[i].size);
3062 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3067 outsize = set_message(outbuf,2,28*count+3,False);
3068 SSVAL(outbuf,smb_vwv0,count);
3069 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3070 SCVAL(smb_buf(outbuf),0,1);
3071 SSVAL(smb_buf(outbuf),1,28*count);
3076 DEBUG(3,("%d entries returned in queue\n",count));
3079 END_PROFILE(SMBsplretq);
3083 /****************************************************************************
3084 Reply to a printwrite.
3085 ****************************************************************************/
3087 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3090 int outsize = set_message(outbuf,0,0,True);
3092 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3094 START_PROFILE(SMBsplwr);
3096 if (!CAN_PRINT(conn)) {
3097 END_PROFILE(SMBsplwr);
3098 return ERROR_DOS(ERRDOS,ERRnoaccess);
3101 CHECK_FSP(fsp,conn);
3104 numtowrite = SVAL(smb_buf(inbuf),1);
3105 data = smb_buf(inbuf) + 3;
3107 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3108 END_PROFILE(SMBsplwr);
3109 return(UNIXERROR(ERRHRD,ERRdiskfull));
3112 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3114 END_PROFILE(SMBsplwr);
3118 /****************************************************************************
3119 The guts of the mkdir command, split out so it may be called by the NT SMB
3121 ****************************************************************************/
3123 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3125 BOOL bad_path = False;
3126 SMB_STRUCT_STAT sbuf;
3129 unix_convert(directory,conn,0,&bad_path,&sbuf);
3131 if( strchr_m(directory, ':')) {
3132 return NT_STATUS_NOT_A_DIRECTORY;
3135 if (ms_has_wild(directory)) {
3136 return NT_STATUS_OBJECT_NAME_INVALID;
3139 if (check_name(directory, conn))
3140 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3143 if(errno == ENOENT) {
3145 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3147 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3149 return map_nt_error_from_unix(errno);
3152 return NT_STATUS_OK;
3155 /****************************************************************************
3157 ****************************************************************************/
3159 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3164 START_PROFILE(SMBmkdir);
3166 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3167 if (!NT_STATUS_IS_OK(status)) {
3168 END_PROFILE(SMBmkdir);
3169 return ERROR_NT(status);
3172 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3174 status = mkdir_internal(conn, directory);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 END_PROFILE(SMBmkdir);
3177 return ERROR_NT(status);
3180 outsize = set_message(outbuf,0,0,True);
3182 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3184 END_PROFILE(SMBmkdir);
3188 /****************************************************************************
3189 Static function used by reply_rmdir to delete an entire directory
3190 tree recursively. Return False on ok, True on fail.
3191 ****************************************************************************/
3193 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3195 const char *dname = NULL;
3197 void *dirptr = OpenDir(conn, directory, False);
3202 while((dname = ReadDirName(dirptr))) {
3206 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3209 /* Construct the full name. */
3210 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3216 pstrcpy(fullname, directory);
3217 pstrcat(fullname, "/");
3218 pstrcat(fullname, dname);
3220 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3225 if(st.st_mode & S_IFDIR) {
3226 if(recursive_rmdir(conn, fullname)!=0) {
3230 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3234 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3243 /****************************************************************************
3244 The internals of the rmdir code - called elsewhere.
3245 ****************************************************************************/
3247 BOOL rmdir_internals(connection_struct *conn, char *directory)
3251 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3252 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3254 * Check to see if the only thing in this directory are
3255 * vetoed files/directories. If so then delete them and
3256 * retry. If we fail to delete any of them (and we *don't*
3257 * do a recursive delete) then fail the rmdir.
3259 BOOL all_veto_files = True;
3261 void *dirptr = OpenDir(conn, directory, False);
3263 if(dirptr != NULL) {
3264 int dirpos = TellDir(dirptr);
3265 while ((dname = ReadDirName(dirptr))) {
3266 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3268 if(!IS_VETO_PATH(conn, dname)) {
3269 all_veto_files = False;
3274 if(all_veto_files) {
3275 SeekDir(dirptr,dirpos);
3276 while ((dname = ReadDirName(dirptr))) {
3280 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3283 /* Construct the full name. */
3284 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3289 pstrcpy(fullname, directory);
3290 pstrcat(fullname, "/");
3291 pstrcat(fullname, dname);
3293 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3295 if(st.st_mode & S_IFDIR) {
3296 if(lp_recursive_veto_delete(SNUM(conn))) {
3297 if(recursive_rmdir(conn, fullname) != 0)
3300 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3302 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3306 /* Retry the rmdir */
3307 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3317 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3322 /****************************************************************************
3324 ****************************************************************************/
3326 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3331 BOOL bad_path = False;
3332 SMB_STRUCT_STAT sbuf;
3334 START_PROFILE(SMBrmdir);
3336 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3337 if (!NT_STATUS_IS_OK(status)) {
3338 END_PROFILE(SMBrmdir);
3339 return ERROR_NT(status);
3342 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3344 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3346 if (check_name(directory,conn)) {
3347 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3348 ok = rmdir_internals(conn, directory);
3352 END_PROFILE(SMBrmdir);
3353 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3356 outsize = set_message(outbuf,0,0,True);
3358 DEBUG( 3, ( "rmdir %s\n", directory ) );
3360 END_PROFILE(SMBrmdir);
3364 /*******************************************************************
3365 Resolve wildcards in a filename rename.
3366 Note that name is in UNIX charset and thus potentially can be more
3367 than fstring buffer (255 bytes) especially in default UTF-8 case.
3368 Therefore, we use pstring inside and all calls should ensure that
3369 name2 is at least pstring-long (they do already)
3370 ********************************************************************/
3372 static BOOL resolve_wildcards(const char *name1, char *name2)
3374 pstring root1,root2;
3376 char *p,*p2, *pname1, *pname2;
3377 int available_space, actual_space;
3380 pname1 = strrchr_m(name1,'/');
3381 pname2 = strrchr_m(name2,'/');
3383 if (!pname1 || !pname2)
3386 pstrcpy(root1,pname1);
3387 pstrcpy(root2,pname2);
3388 p = strrchr_m(root1,'.');
3395 p = strrchr_m(root2,'.');
3429 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3432 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3433 if (actual_space >= available_space - 1) {
3434 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3435 actual_space - available_space));
3438 pstrcpy_base(pname2, root2, name2);
3444 /****************************************************************************
3445 Ensure open files have their names updates.
3446 ****************************************************************************/
3448 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3451 BOOL did_rename = False;
3453 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3454 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3455 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3456 fsp->fsp_name, newname ));
3457 string_set(&fsp->fsp_name, newname);
3462 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3463 (unsigned int)dev, (double)inode, newname ));
3466 /****************************************************************************
3467 Rename an open file - given an fsp.
3468 ****************************************************************************/
3470 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3472 SMB_STRUCT_STAT sbuf;
3473 BOOL bad_path = False;
3474 pstring newname_last_component;
3475 NTSTATUS error = NT_STATUS_OK;
3480 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3482 /* Quick check for "." and ".." */
3483 if (!bad_path && newname_last_component[0] == '.') {
3484 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3485 return NT_STATUS_ACCESS_DENIED;
3488 if (!rcdest && bad_path) {
3489 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3492 /* Ensure newname contains a '/' */
3493 if(strrchr_m(newname,'/') == 0) {
3496 pstrcpy(tmpstr, "./");
3497 pstrcat(tmpstr, newname);
3498 pstrcpy(newname, tmpstr);
3502 * Check for special case with case preserving and not
3503 * case sensitive. If the old last component differs from the original
3504 * last component only by case, then we should allow
3505 * the rename (user is trying to change the case of the
3509 if((case_sensitive == False) && (case_preserve == True) &&
3510 strequal(newname, fsp->fsp_name)) {
3512 pstring newname_modified_last_component;
3515 * Get the last component of the modified name.
3516 * Note that we guarantee that newname contains a '/'
3519 p = strrchr_m(newname,'/');
3520 pstrcpy(newname_modified_last_component,p+1);
3522 if(strcsequal(newname_modified_last_component,
3523 newname_last_component) == False) {
3525 * Replace the modified last component with
3528 pstrcpy(p+1, newname_last_component);
3533 * If the src and dest names are identical - including case,
3534 * don't do the rename, just return success.
3537 if (strcsequal(fsp->fsp_name, newname)) {
3538 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3540 return NT_STATUS_OK;
3543 dest_exists = vfs_object_exist(conn,newname,NULL);
3545 if(!replace_if_exists && dest_exists) {
3546 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3547 fsp->fsp_name,newname));
3548 return NT_STATUS_OBJECT_NAME_COLLISION;
3551 error = can_rename(newname,conn,&sbuf);
3553 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3554 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3555 nt_errstr(error), fsp->fsp_name,newname));
3556 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3557 error = NT_STATUS_ACCESS_DENIED;
3561 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3562 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3563 fsp->fsp_name,newname));
3564 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3565 return NT_STATUS_OK;
3568 if (errno == ENOTDIR || errno == EISDIR)
3569 error = NT_STATUS_OBJECT_NAME_COLLISION;
3571 error = map_nt_error_from_unix(errno);
3573 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3574 nt_errstr(error), fsp->fsp_name,newname));
3579 /****************************************************************************
3580 The guts of the rename command, split out so it may be called by the NT SMB
3582 ****************************************************************************/
3584 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3588 pstring last_component_src;
3589 pstring last_component_dest;
3592 BOOL bad_path_src = False;
3593 BOOL bad_path_dest = False;
3595 NTSTATUS error = NT_STATUS_OK;
3598 SMB_STRUCT_STAT sbuf1, sbuf2;
3600 *directory = *mask = 0;
3605 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3606 if (!rc && bad_path_src) {
3607 if (ms_has_wild(last_component_src))
3608 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3609 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3612 /* Quick check for "." and ".." */
3613 if (last_component_src[0] == '.') {
3614 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3615 return NT_STATUS_OBJECT_NAME_INVALID;
3619 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3621 /* Quick check for "." and ".." */
3622 if (last_component_dest[0] == '.') {
3623 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3624 return NT_STATUS_OBJECT_NAME_INVALID;
3629 * Split the old name into directory and last component
3630 * strings. Note that unix_convert may have stripped off a
3631 * leading ./ from both name and newname if the rename is
3632 * at the root of the share. We need to make sure either both
3633 * name and newname contain a / character or neither of them do
3634 * as this is checked in resolve_wildcards().
3637 p = strrchr_m(name,'/');
3639 pstrcpy(directory,".");
3643 pstrcpy(directory,name);
3645 *p = '/'; /* Replace needed for exceptional test below. */
3649 * We should only check the mangled cache
3650 * here if unix_convert failed. This means
3651 * that the path in 'mask' doesn't exist
3652 * on the file system and so we need to look
3653 * for a possible mangle. This patch from
3654 * Tine Smukavec <valentin.smukavec@hermes.si>.
3657 if (!rc && mangle_is_mangled(mask))
3658 mangle_check_cache( mask );
3660 has_wild = ms_has_wild(mask);
3664 * No wildcards - just process the one file.
3666 BOOL is_short_name = mangle_is_8_3(name, True);
3668 /* Add a terminating '/' to the directory name. */
3669 pstrcat(directory,"/");
3670 pstrcat(directory,mask);
3672 /* Ensure newname contains a '/' also */
3673 if(strrchr_m(newname,'/') == 0) {
3676 pstrcpy(tmpstr, "./");
3677 pstrcat(tmpstr, newname);
3678 pstrcpy(newname, tmpstr);
3681 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3682 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3683 case_sensitive, case_preserve, short_case_preserve, directory,
3684 newname, last_component_dest, is_short_name));
3687 * Check for special case with case preserving and not
3688 * case sensitive, if directory and newname are identical,
3689 * and the old last component differs from the original
3690 * last component only by case, then we should allow
3691 * the rename (user is trying to change the case of the
3694 if((case_sensitive == False) &&
3695 (((case_preserve == True) &&
3696 (is_short_name == False)) ||
3697 ((short_case_preserve == True) &&
3698 (is_short_name == True))) &&
3699 strcsequal(directory, newname)) {
3700 pstring modified_last_component;
3703 * Get the last component of the modified name.
3704 * Note that we guarantee that newname contains a '/'
3707 p = strrchr_m(newname,'/');
3708 pstrcpy(modified_last_component,p+1);
3710 if(strcsequal(modified_last_component,
3711 last_component_dest) == False) {
3713 * Replace the modified last component with
3716 pstrcpy(p+1, last_component_dest);
3720 resolve_wildcards(directory,newname);
3723 * The source object must exist.
3726 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3727 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3728 directory,newname));
3730 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3732 * Must return different errors depending on whether the parent
3733 * directory existed or not.
3736 p = strrchr_m(directory, '/');
3738 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3740 if (vfs_object_exist(conn, directory, NULL))
3741 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3742 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3744 error = map_nt_error_from_unix(errno);
3745 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3746 nt_errstr(error), directory,newname));
3751 if (!rcdest && bad_path_dest) {
3752 if (ms_has_wild(last_component_dest))
3753 return NT_STATUS_OBJECT_NAME_INVALID;
3754 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3757 error = can_rename(directory,conn,&sbuf1);
3759 if (!NT_STATUS_IS_OK(error)) {
3760 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3761 nt_errstr(error), directory,newname));
3766 * If the src and dest names are identical - including case,
3767 * don't do the rename, just return success.
3770 if (strcsequal(directory, newname)) {
3771 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3772 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3773 return NT_STATUS_OK;
3776 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3777 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3778 directory,newname));
3779 return NT_STATUS_OBJECT_NAME_COLLISION;
3782 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3783 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3784 directory,newname));
3785 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3786 return NT_STATUS_OK;
3789 if (errno == ENOTDIR || errno == EISDIR)
3790 error = NT_STATUS_OBJECT_NAME_COLLISION;
3792 error = map_nt_error_from_unix(errno);
3794 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3795 nt_errstr(error), directory,newname));
3800 * Wildcards - process each file that matches.
3802 void *dirptr = NULL;
3806 if (check_name(directory,conn))
3807 dirptr = OpenDir(conn, directory, True);
3810 error = NT_STATUS_NO_SUCH_FILE;
3811 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3813 if (strequal(mask,"????????.???"))
3816 while ((dname = ReadDirName(dirptr))) {
3818 BOOL sysdir_entry = False;
3820 pstrcpy(fname,dname);
3822 /* Quick check for "." and ".." */
3823 if (fname[0] == '.') {
3824 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3826 sysdir_entry = True;
3833 if(!mask_match(fname, mask, case_sensitive))
3837 error = NT_STATUS_OBJECT_NAME_INVALID;
3841 error = NT_STATUS_ACCESS_DENIED;
3842 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3843 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3844 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3845 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3848 error = can_rename(fname,conn,&sbuf1);
3849 if (!NT_STATUS_IS_OK(error)) {
3850 DEBUG(6,("rename %s refused\n", fname));
3853 pstrcpy(destname,newname);
3855 if (!resolve_wildcards(fname,destname)) {
3856 DEBUG(6,("resolve_wildcards %s %s failed\n",
3861 if (!replace_if_exists &&
3862 vfs_file_exist(conn,destname, NULL)) {
3863 DEBUG(6,("file_exist %s\n", destname));
3864 error = NT_STATUS_OBJECT_NAME_COLLISION;
3868 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3869 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3871 error = NT_STATUS_OK;
3873 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3878 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3879 if (!rcdest && bad_path_dest) {
3880 if (ms_has_wild(last_component_dest))
3881 return NT_STATUS_OBJECT_NAME_INVALID;
3882 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3887 if (count == 0 && NT_STATUS_IS_OK(error)) {
3888 error = map_nt_error_from_unix(errno);
3894 /****************************************************************************
3896 ****************************************************************************/
3898 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3905 uint16 attrs = SVAL(inbuf,smb_vwv0);
3908 START_PROFILE(SMBmv);
3910 p = smb_buf(inbuf) + 1;
3911 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3912 if (!NT_STATUS_IS_OK(status)) {
3914 return ERROR_NT(status);
3917 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3918 if (!NT_STATUS_IS_OK(status)) {
3920 return ERROR_NT(status);
3923 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3924 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3926 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3928 status = rename_internals(conn, name, newname, attrs, False);
3929 if (!NT_STATUS_IS_OK(status)) {
3931 return ERROR_NT(status);
3935 * Win2k needs a changenotify request response before it will
3936 * update after a rename..
3938 process_pending_change_notify_queue((time_t)0);
3939 outsize = set_message(outbuf,0,0,True);
3945 /*******************************************************************
3946 Copy a file as part of a reply_copy.
3947 ******************************************************************/
3949 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3950 int count,BOOL target_is_directory, int *err_ret)
3953 SMB_STRUCT_STAT src_sbuf, sbuf2;
3955 files_struct *fsp1,*fsp2;
3960 pstrcpy(dest,dest1);
3961 if (target_is_directory) {
3962 char *p = strrchr_m(src,'/');
3971 if (!vfs_file_exist(conn,src,&src_sbuf))
3974 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3975 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3980 if (!target_is_directory && count)
3981 ofun = FILE_EXISTS_OPEN;
3983 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3984 ZERO_STRUCTP(&sbuf2);
3986 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3987 ofun,src_sbuf.st_mode,0,&Access,&action);
3990 close_file(fsp1,False);
3994 if ((ofun&3) == 1) {
3995 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3996 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3998 * Stop the copy from occurring.
4001 src_sbuf.st_size = 0;
4005 if (src_sbuf.st_size)
4006 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4008 close_file(fsp1,False);
4010 /* Ensure the modtime is set correctly on the destination file. */
4011 fsp2->pending_modtime = src_sbuf.st_mtime;
4014 * As we are opening fsp1 read-only we only expect
4015 * an error on close on fsp2 if we are out of space.
4016 * Thus we don't look at the error return from the
4019 *err_ret = close_file(fsp2,False);
4021 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4024 /****************************************************************************
4025 Reply to a file copy.
4026 ****************************************************************************/
4028 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4033 pstring mask,newname;
4036 int error = ERRnoaccess;
4040 int tid2 = SVAL(inbuf,smb_vwv0);
4041 int ofun = SVAL(inbuf,smb_vwv1);
4042 int flags = SVAL(inbuf,smb_vwv2);
4043 BOOL target_is_directory=False;
4044 BOOL bad_path1 = False;
4045 BOOL bad_path2 = False;
4047 SMB_STRUCT_STAT sbuf1, sbuf2;
4050 START_PROFILE(SMBcopy);
4052 *directory = *mask = 0;
4055 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 END_PROFILE(SMBcopy);
4058 return ERROR_NT(status);
4060 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4061 if (!NT_STATUS_IS_OK(status)) {
4062 END_PROFILE(SMBcopy);
4063 return ERROR_NT(status);
4066 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4068 if (tid2 != conn->cnum) {
4069 /* can't currently handle inter share copies XXXX */
4070 DEBUG(3,("Rejecting inter-share copy\n"));
4071 END_PROFILE(SMBcopy);
4072 return ERROR_DOS(ERRSRV,ERRinvdevice);
4075 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4076 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4078 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4079 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4081 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4083 if ((flags&1) && target_is_directory) {
4084 END_PROFILE(SMBcopy);
4085 return ERROR_DOS(ERRDOS,ERRbadfile);
4088 if ((flags&2) && !target_is_directory) {
4089 END_PROFILE(SMBcopy);
4090 return ERROR_DOS(ERRDOS,ERRbadpath);
4093 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4094 /* wants a tree copy! XXXX */
4095 DEBUG(3,("Rejecting tree copy\n"));
4096 END_PROFILE(SMBcopy);
4097 return ERROR_DOS(ERRSRV,ERRerror);
4100 p = strrchr_m(name,'/');
4102 pstrcpy(directory,"./");
4106 pstrcpy(directory,name);
4111 * We should only check the mangled cache
4112 * here if unix_convert failed. This means
4113 * that the path in 'mask' doesn't exist
4114 * on the file system and so we need to look
4115 * for a possible mangle. This patch from
4116 * Tine Smukavec <valentin.smukavec@hermes.si>.
4119 if (!rc && mangle_is_mangled(mask))
4120 mangle_check_cache( mask );
4122 has_wild = ms_has_wild(mask);
4125 pstrcat(directory,"/");
4126 pstrcat(directory,mask);
4127 if (resolve_wildcards(directory,newname) &&
4128 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4132 END_PROFILE(SMBcopy);
4133 return(UNIXERROR(ERRHRD,ERRgeneral));
4136 exists = vfs_file_exist(conn,directory,NULL);
4139 void *dirptr = NULL;
4143 if (check_name(directory,conn))
4144 dirptr = OpenDir(conn, directory, True);
4149 if (strequal(mask,"????????.???"))
4152 while ((dname = ReadDirName(dirptr))) {
4154 pstrcpy(fname,dname);
4156 if(!mask_match(fname, mask, case_sensitive))
4159 error = ERRnoaccess;
4160 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4161 pstrcpy(destname,newname);
4162 if (resolve_wildcards(fname,destname) &&
4163 copy_file(fname,destname,conn,ofun,
4164 count,target_is_directory,&err))
4166 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4174 /* Error on close... */
4176 END_PROFILE(SMBcopy);
4177 return(UNIXERROR(ERRHRD,ERRgeneral));
4181 END_PROFILE(SMBcopy);
4182 return ERROR_DOS(ERRDOS,error);
4184 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4185 unix_ERR_class = ERRDOS;
4186 unix_ERR_code = ERRbadpath;
4188 END_PROFILE(SMBcopy);
4189 return(UNIXERROR(ERRDOS,error));
4193 outsize = set_message(outbuf,1,0,True);
4194 SSVAL(outbuf,smb_vwv0,count);
4196 END_PROFILE(SMBcopy);
4200 /****************************************************************************
4202 ****************************************************************************/
4204 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4212 START_PROFILE(pathworks_setdir);
4215 if (!CAN_SETDIR(snum)) {
4216 END_PROFILE(pathworks_setdir);
4217 return ERROR_DOS(ERRDOS,ERRnoaccess);
4220 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4221 if (!NT_STATUS_IS_OK(status)) {
4222 END_PROFILE(pathworks_setdir);
4223 return ERROR_NT(status);
4226 if (strlen(newdir) == 0) {
4229 ok = vfs_directory_exist(conn,newdir,NULL);
4231 string_set(&conn->connectpath,newdir);
4235 END_PROFILE(pathworks_setdir);
4236 return ERROR_DOS(ERRDOS,ERRbadpath);
4239 outsize = set_message(outbuf,0,0,True);
4240 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4242 DEBUG(3,("setdir %s\n", newdir));
4244 END_PROFILE(pathworks_setdir);
4248 /****************************************************************************
4249 Get a lock pid, dealing with large count requests.
4250 ****************************************************************************/
4252 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4254 if(!large_file_format)
4255 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4257 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4260 /****************************************************************************
4261 Get a lock count, dealing with large count requests.
4262 ****************************************************************************/
4264 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4266 SMB_BIG_UINT count = 0;
4268 if(!large_file_format) {
4269 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4272 #if defined(HAVE_LONGLONG)
4273 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4274 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4275 #else /* HAVE_LONGLONG */
4278 * NT4.x seems to be broken in that it sends large file (64 bit)
4279 * lockingX calls even if the CAP_LARGE_FILES was *not*
4280 * negotiated. For boxes without large unsigned ints truncate the
4281 * lock count by dropping the top 32 bits.
4284 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4285 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4286 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4287 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4288 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4291 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4292 #endif /* HAVE_LONGLONG */
4298 #if !defined(HAVE_LONGLONG)
4299 /****************************************************************************
4300 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4301 ****************************************************************************/
4303 static uint32 map_lock_offset(uint32 high, uint32 low)
4307 uint32 highcopy = high;
4310 * Try and find out how many significant bits there are in high.
4313 for(i = 0; highcopy; i++)
4317 * We use 31 bits not 32 here as POSIX
4318 * lock offsets may not be negative.
4321 mask = (~0) << (31 - i);
4324 return 0; /* Fail. */
4330 #endif /* !defined(HAVE_LONGLONG) */
4332 /****************************************************************************
4333 Get a lock offset, dealing with large offset requests.
4334 ****************************************************************************/
4336 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4338 SMB_BIG_UINT offset = 0;
4342 if(!large_file_format) {
4343 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4346 #if defined(HAVE_LONGLONG)
4347 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4348 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4349 #else /* HAVE_LONGLONG */
4352 * NT4.x seems to be broken in that it sends large file (64 bit)
4353 * lockingX calls even if the CAP_LARGE_FILES was *not*
4354 * negotiated. For boxes without large unsigned ints mangle the
4355 * lock offset by mapping the top 32 bits onto the lower 32.
4358 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4359 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4360 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4363 if((new_low = map_lock_offset(high, low)) == 0) {
4365 return (SMB_BIG_UINT)-1;
4368 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4369 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4370 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4371 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4374 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4375 #endif /* HAVE_LONGLONG */
4381 /****************************************************************************
4382 Reply to a lockingX request.
4383 ****************************************************************************/
4385 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4387 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4388 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4389 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4390 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4391 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4392 SMB_BIG_UINT count = 0, offset = 0;
4394 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4397 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4399 BOOL my_lock_ctx = False;
4402 START_PROFILE(SMBlockingX);
4404 CHECK_FSP(fsp,conn);
4406 data = smb_buf(inbuf);
4408 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4409 /* we don't support these - and CANCEL_LOCK makes w2k
4410 and XP reboot so I don't really want to be
4411 compatible! (tridge) */
4412 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4415 /* Check if this is an oplock break on a file
4416 we have granted an oplock on.
4418 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4419 /* Client can insist on breaking to none. */
4420 BOOL break_to_none = (oplocklevel == 0);
4422 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4423 (unsigned int)oplocklevel, fsp->fnum ));
4426 * Make sure we have granted an exclusive or batch oplock on this file.
4429 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4430 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4431 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4433 /* if this is a pure oplock break request then don't send a reply */
4434 if (num_locks == 0 && num_ulocks == 0) {
4435 END_PROFILE(SMBlockingX);
4438 END_PROFILE(SMBlockingX);
4439 return ERROR_DOS(ERRDOS,ERRlock);
4443 if (remove_oplock(fsp, break_to_none) == False) {
4444 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4448 /* if this is a pure oplock break request then don't send a reply */
4449 if (num_locks == 0 && num_ulocks == 0) {
4450 /* Sanity check - ensure a pure oplock break is not a
4452 if(CVAL(inbuf,smb_vwv0) != 0xff)
4453 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4454 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4455 END_PROFILE(SMBlockingX);
4461 * We do this check *after* we have checked this is not a oplock break
4462 * response message. JRA.
4465 release_level_2_oplocks_on_change(fsp);
4467 /* Data now points at the beginning of the list
4468 of smb_unlkrng structs */
4469 for(i = 0; i < (int)num_ulocks; i++) {
4470 lock_pid = get_lock_pid( data, i, large_file_format);
4471 count = get_lock_count( data, i, large_file_format);
4472 offset = get_lock_offset( data, i, large_file_format, &err);
4475 * There is no error code marked "stupid client bug".... :-).
4478 END_PROFILE(SMBlockingX);
4479 return ERROR_DOS(ERRDOS,ERRnoaccess);
4482 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4483 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4485 status = do_unlock(fsp,conn,lock_pid,count,offset);
4486 if (NT_STATUS_V(status)) {
4487 END_PROFILE(SMBlockingX);
4488 return ERROR_NT(status);
4492 /* Setup the timeout in seconds. */
4494 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4496 /* Now do any requested locks */
4497 data += ((large_file_format ? 20 : 10)*num_ulocks);
4499 /* Data now points at the beginning of the list
4500 of smb_lkrng structs */
4502 for(i = 0; i < (int)num_locks; i++) {
4503 lock_pid = get_lock_pid( data, i, large_file_format);
4504 count = get_lock_count( data, i, large_file_format);
4505 offset = get_lock_offset( data, i, large_file_format, &err);
4508 * There is no error code marked "stupid client bug".... :-).
4511 END_PROFILE(SMBlockingX);
4512 return ERROR_DOS(ERRDOS,ERRnoaccess);
4515 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4516 (double)offset, (double)count, (unsigned int)lock_pid,
4517 fsp->fsp_name, (int)lock_timeout ));
4519 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4520 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4521 if (NT_STATUS_V(status)) {
4523 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4524 * Even if it's our own lock context, we need to wait here as
4525 * there may be an unlock on the way.
4526 * So I removed a "&& !my_lock_ctx" from the following
4527 * if statement. JRA.
4529 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4531 * A blocking lock was requested. Package up
4532 * this smb into a queued request and push it
4533 * onto the blocking lock queue.
4535 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4536 END_PROFILE(SMBlockingX);
4544 /* If any of the above locks failed, then we must unlock
4545 all of the previous locks (X/Open spec). */
4546 if (i != num_locks && num_locks != 0) {
4548 * Ensure we don't do a remove on the lock that just failed,
4549 * as under POSIX rules, if we have a lock already there, we
4550 * will delete it (and we shouldn't) .....
4552 for(i--; i >= 0; i--) {
4553 lock_pid = get_lock_pid( data, i, large_file_format);
4554 count = get_lock_count( data, i, large_file_format);
4555 offset = get_lock_offset( data, i, large_file_format, &err);
4558 * There is no error code marked "stupid client bug".... :-).
4561 END_PROFILE(SMBlockingX);
4562 return ERROR_DOS(ERRDOS,ERRnoaccess);
4565 do_unlock(fsp,conn,lock_pid,count,offset);
4567 END_PROFILE(SMBlockingX);
4568 return ERROR_NT(status);
4571 set_message(outbuf,2,0,True);
4573 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4574 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4576 END_PROFILE(SMBlockingX);
4577 return chain_reply(inbuf,outbuf,length,bufsize);
4580 /****************************************************************************
4581 Reply to a SMBreadbmpx (read block multiplex) request.
4582 ****************************************************************************/
4584 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4595 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4596 START_PROFILE(SMBreadBmpx);
4598 /* this function doesn't seem to work - disable by default */
4599 if (!lp_readbmpx()) {
4600 END_PROFILE(SMBreadBmpx);
4601 return ERROR_DOS(ERRSRV,ERRuseSTD);
4604 outsize = set_message(outbuf,8,0,True);
4606 CHECK_FSP(fsp,conn);
4609 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4610 maxcount = SVAL(inbuf,smb_vwv3);
4612 data = smb_buf(outbuf);
4613 pad = ((long)data)%4;
4618 max_per_packet = bufsize-(outsize+pad);
4622 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4623 END_PROFILE(SMBreadBmpx);
4624 return ERROR_DOS(ERRDOS,ERRlock);
4628 size_t N = MIN(max_per_packet,tcount-total_read);
4630 nread = read_file(fsp,data,startpos,N);
4635 if (nread < (ssize_t)N)
4636 tcount = total_read + nread;
4638 set_message(outbuf,8,nread,False);
4639 SIVAL(outbuf,smb_vwv0,startpos);
4640 SSVAL(outbuf,smb_vwv2,tcount);
4641 SSVAL(outbuf,smb_vwv6,nread);
4642 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4644 if (!send_smb(smbd_server_fd(),outbuf))
4645 exit_server("reply_readbmpx: send_smb failed.");
4647 total_read += nread;
4649 } while (total_read < (ssize_t)tcount);
4651 END_PROFILE(SMBreadBmpx);
4655 /****************************************************************************
4656 Reply to a SMBsetattrE.
4657 ****************************************************************************/
4659 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4661 struct utimbuf unix_times;
4663 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4664 START_PROFILE(SMBsetattrE);
4666 outsize = set_message(outbuf,0,0,True);
4668 if(!fsp || (fsp->conn != conn)) {
4669 END_PROFILE(SMBgetattrE);
4670 return ERROR_DOS(ERRDOS,ERRbadfid);
4674 * Convert the DOS times into unix times. Ignore create
4675 * time as UNIX can't set this.
4678 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4679 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4682 * Patch from Ray Frush <frush@engr.colostate.edu>
4683 * Sometimes times are sent as zero - ignore them.
4686 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4687 /* Ignore request */
4688 if( DEBUGLVL( 3 ) ) {
4689 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4690 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4692 END_PROFILE(SMBsetattrE);
4694 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4695 /* set modify time = to access time if modify time was 0 */
4696 unix_times.modtime = unix_times.actime;
4699 /* Set the date on this file */
4700 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4701 END_PROFILE(SMBsetattrE);
4702 return ERROR_DOS(ERRDOS,ERRnoaccess);
4705 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4706 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4708 END_PROFILE(SMBsetattrE);
4713 /* Back from the dead for OS/2..... JRA. */
4715 /****************************************************************************
4716 Reply to a SMBwritebmpx (write block multiplex primary) request.
4717 ****************************************************************************/
4719 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4722 ssize_t nwritten = -1;
4729 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4730 START_PROFILE(SMBwriteBmpx);
4732 CHECK_FSP(fsp,conn);
4736 tcount = SVAL(inbuf,smb_vwv1);
4737 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4738 write_through = BITSETW(inbuf+smb_vwv7,0);
4739 numtowrite = SVAL(inbuf,smb_vwv10);
4740 smb_doff = SVAL(inbuf,smb_vwv11);
4742 data = smb_base(inbuf) + smb_doff;
4744 /* If this fails we need to send an SMBwriteC response,
4745 not an SMBwritebmpx - set this up now so we don't forget */
4746 SCVAL(outbuf,smb_com,SMBwritec);
4748 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4749 END_PROFILE(SMBwriteBmpx);
4750 return(ERROR_DOS(ERRDOS,ERRlock));
4753 nwritten = write_file(fsp,data,startpos,numtowrite);
4755 if(lp_syncalways(SNUM(conn)) || write_through)
4756 sync_file(conn,fsp);
4758 if(nwritten < (ssize_t)numtowrite) {
4759 END_PROFILE(SMBwriteBmpx);
4760 return(UNIXERROR(ERRHRD,ERRdiskfull));
4763 /* If the maximum to be written to this file
4764 is greater than what we just wrote then set
4765 up a secondary struct to be attached to this
4766 fd, we will use this to cache error messages etc. */
4768 if((ssize_t)tcount > nwritten) {
4769 write_bmpx_struct *wbms;
4770 if(fsp->wbmpx_ptr != NULL)
4771 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4773 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4775 DEBUG(0,("Out of memory in reply_readmpx\n"));
4776 END_PROFILE(SMBwriteBmpx);
4777 return(ERROR_DOS(ERRSRV,ERRnoresource));
4779 wbms->wr_mode = write_through;
4780 wbms->wr_discard = False; /* No errors yet */
4781 wbms->wr_total_written = nwritten;
4782 wbms->wr_errclass = 0;
4784 fsp->wbmpx_ptr = wbms;
4787 /* We are returning successfully, set the message type back to
4789 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4791 outsize = set_message(outbuf,1,0,True);
4793 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4795 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4796 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4798 if (write_through && tcount==nwritten) {
4799 /* We need to send both a primary and a secondary response */
4800 smb_setlen(outbuf,outsize - 4);
4801 if (!send_smb(smbd_server_fd(),outbuf))
4802 exit_server("reply_writebmpx: send_smb failed.");
4804 /* Now the secondary */
4805 outsize = set_message(outbuf,1,0,True);
4806 SCVAL(outbuf,smb_com,SMBwritec);
4807 SSVAL(outbuf,smb_vwv0,nwritten);
4810 END_PROFILE(SMBwriteBmpx);
4814 /****************************************************************************
4815 Reply to a SMBwritebs (write block multiplex secondary) request.
4816 ****************************************************************************/
4818 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4821 ssize_t nwritten = -1;
4828 write_bmpx_struct *wbms;
4829 BOOL send_response = False;
4830 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4831 START_PROFILE(SMBwriteBs);
4833 CHECK_FSP(fsp,conn);
4836 tcount = SVAL(inbuf,smb_vwv1);
4837 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4838 numtowrite = SVAL(inbuf,smb_vwv6);
4839 smb_doff = SVAL(inbuf,smb_vwv7);
4841 data = smb_base(inbuf) + smb_doff;
4843 /* We need to send an SMBwriteC response, not an SMBwritebs */
4844 SCVAL(outbuf,smb_com,SMBwritec);
4846 /* This fd should have an auxiliary struct attached,
4847 check that it does */
4848 wbms = fsp->wbmpx_ptr;
4850 END_PROFILE(SMBwriteBs);
4854 /* If write through is set we can return errors, else we must cache them */
4855 write_through = wbms->wr_mode;
4857 /* Check for an earlier error */
4858 if(wbms->wr_discard) {
4859 END_PROFILE(SMBwriteBs);
4860 return -1; /* Just discard the packet */
4863 nwritten = write_file(fsp,data,startpos,numtowrite);
4865 if(lp_syncalways(SNUM(conn)) || write_through)
4866 sync_file(conn,fsp);
4868 if (nwritten < (ssize_t)numtowrite) {
4870 /* We are returning an error - we can delete the aux struct */
4873 fsp->wbmpx_ptr = NULL;
4874 END_PROFILE(SMBwriteBs);
4875 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4877 END_PROFILE(SMBwriteBs);
4878 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4881 /* Increment the total written, if this matches tcount
4882 we can discard the auxiliary struct (hurrah !) and return a writeC */
4883 wbms->wr_total_written += nwritten;
4884 if(wbms->wr_total_written >= tcount) {
4885 if (write_through) {
4886 outsize = set_message(outbuf,1,0,True);
4887 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4888 send_response = True;
4892 fsp->wbmpx_ptr = NULL;
4896 END_PROFILE(SMBwriteBs);
4900 END_PROFILE(SMBwriteBs);
4904 /****************************************************************************
4905 Reply to a SMBgetattrE.
4906 ****************************************************************************/
4908 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4910 SMB_STRUCT_STAT sbuf;
4913 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4914 START_PROFILE(SMBgetattrE);
4916 outsize = set_message(outbuf,11,0,True);
4918 if(!fsp || (fsp->conn != conn)) {
4919 END_PROFILE(SMBgetattrE);
4920 return ERROR_DOS(ERRDOS,ERRbadfid);
4923 /* Do an fstat on this file */
4924 if(fsp_stat(fsp, &sbuf)) {
4925 END_PROFILE(SMBgetattrE);
4926 return(UNIXERROR(ERRDOS,ERRnoaccess));
4929 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4932 * Convert the times into dos times. Set create
4933 * date to be last modify date as UNIX doesn't save
4937 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4938 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4939 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4942 SIVAL(outbuf,smb_vwv6,0);
4943 SIVAL(outbuf,smb_vwv8,0);
4945 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4946 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4947 SIVAL(outbuf,smb_vwv8,allocation_size);
4949 SSVAL(outbuf,smb_vwv10, mode);
4951 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4953 END_PROFILE(SMBgetattrE);