2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
33 extern char magic_char;
34 extern int global_oplock_break;
35 unsigned int smb_echo_count = 0;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
49 const char *s = srcname;
50 NTSTATUS ret = NT_STATUS_OK;
53 if (IS_DIRECTORY_SEP(*s)) {
55 * Safe to assume is not the second part of a mb char as this is handled below.
57 /* Eat multiple '/' or '\\' */
58 while (IS_DIRECTORY_SEP(*s)) {
61 if ((s[0] == '.') && (s[1] == '\0')) {
62 ret = NT_STATUS_OBJECT_NAME_INVALID;
65 if ((d != destname) && (*s != '\0')) {
66 /* We only care about non-leading or trailing '/' or '\\' */
69 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
70 /* Uh oh - "../" or "..\\" or "..\0" ! */
73 * No mb char starts with '.' so we're safe checking the directory separator here.
76 /* If we just added a '/', delete it. */
78 if ((d > destname) && (*(d-1) == '/')) {
80 if (d == (destname + 1)) {
86 /* Are we at the start ? Can't go back further if so. */
88 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
91 /* Go back one level... */
92 /* We know this is safe as '/' cannot be part of a mb sequence. */
93 /* NOTE - if this assumption is invalid we are not in good shape... */
94 while (d > destname) {
100 } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) {
103 * No mb char starts with '.' so we're safe checking the directory separator here.
106 /* "./" or ".\\" fails with a different error depending on where it is... */
109 ret = NT_STATUS_OBJECT_NAME_INVALID;
112 if (s[1] != '\0' && s[2] == '\0') {
113 ret = NT_STATUS_INVALID_PARAMETER;
116 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
124 switch(next_mb_char_size(s)) {
135 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
137 return NT_STATUS_INVALID_PARAMETER;
146 /****************************************************************************
147 Pull a string and check the path - provide for error return.
148 ****************************************************************************/
150 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
153 char *tmppath_ptr = tmppath;
156 SMB_ASSERT(dest_len == sizeof(pstring));
160 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
162 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
164 *err = check_path_syntax(dest, tmppath);
168 /****************************************************************************
169 Reply to a special message.
170 ****************************************************************************/
172 int reply_special(char *inbuf,char *outbuf)
175 int msg_type = CVAL(inbuf,0);
176 int msg_flags = CVAL(inbuf,1);
180 static BOOL already_got_session = False;
184 memset(outbuf,'\0',smb_size);
186 smb_setlen(outbuf,0);
189 case 0x81: /* session request */
191 if (already_got_session) {
192 exit_server("multiple session request not permitted");
195 SCVAL(outbuf,0,0x82);
197 if (name_len(inbuf+4) > 50 ||
198 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
199 DEBUG(0,("Invalid name length in session request\n"));
202 name_extract(inbuf,4,name1);
203 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
204 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
207 set_local_machine_name(name1, True);
208 set_remote_machine_name(name2, True);
210 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
211 get_local_machine_name(), get_remote_machine_name(),
214 if (name_type == 'R') {
215 /* We are being asked for a pathworks session ---
217 SCVAL(outbuf, 0,0x83);
221 /* only add the client's machine name to the list
222 of possibly valid usernames if we are operating
223 in share mode security */
224 if (lp_security() == SEC_SHARE) {
225 add_session_user(get_remote_machine_name());
228 reload_services(True);
231 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
233 already_got_session = True;
236 case 0x89: /* session keepalive request
237 (some old clients produce this?) */
238 SCVAL(outbuf,0,SMBkeepalive);
242 case 0x82: /* positive session response */
243 case 0x83: /* negative session response */
244 case 0x84: /* retarget session response */
245 DEBUG(0,("Unexpected session response\n"));
248 case SMBkeepalive: /* session keepalive */
253 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
254 msg_type, msg_flags));
259 /****************************************************************************
261 ****************************************************************************/
263 int reply_tcon(connection_struct *conn,
264 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
271 uint16 vuid = SVAL(inbuf,smb_uid);
275 DATA_BLOB password_blob;
277 START_PROFILE(SMBtcon);
279 *service_buf = *password = *dev = 0;
281 p = smb_buf(inbuf)+1;
282 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
283 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
285 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
287 p = strrchr_m(service_buf,'\\');
291 service = service_buf;
294 password_blob = data_blob(password, pwlen+1);
296 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
298 data_blob_clear_free(&password_blob);
301 END_PROFILE(SMBtcon);
302 return ERROR_NT(nt_status);
305 outsize = set_message(outbuf,2,0,True);
306 SSVAL(outbuf,smb_vwv0,max_recv);
307 SSVAL(outbuf,smb_vwv1,conn->cnum);
308 SSVAL(outbuf,smb_tid,conn->cnum);
310 DEBUG(3,("tcon service=%s cnum=%d\n",
311 service, conn->cnum));
313 END_PROFILE(SMBtcon);
317 /****************************************************************************
318 Reply to a tcon and X.
319 ****************************************************************************/
321 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
326 /* what the cleint thinks the device is */
327 fstring client_devicetype;
328 /* what the server tells the client the share represents */
329 const char *server_devicetype;
331 uint16 vuid = SVAL(inbuf,smb_uid);
332 int passlen = SVAL(inbuf,smb_vwv3);
335 extern BOOL global_encrypted_passwords_negotiated;
337 START_PROFILE(SMBtconX);
339 *service = *client_devicetype = 0;
341 /* we might have to close an old one */
342 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
343 close_cnum(conn,vuid);
346 if (passlen > MAX_PASS_LEN) {
347 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
350 if (global_encrypted_passwords_negotiated) {
351 password = data_blob(smb_buf(inbuf),passlen);
353 password = data_blob(smb_buf(inbuf),passlen+1);
354 /* Ensure correct termination */
355 password.data[passlen]=0;
358 p = smb_buf(inbuf) + passlen;
359 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
362 * the service name can be either: \\server\share
363 * or share directly like on the DELL PowerVault 705
366 q = strchr_m(path+2,'\\');
368 END_PROFILE(SMBtconX);
369 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
371 fstrcpy(service,q+1);
374 fstrcpy(service,path);
376 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
378 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
380 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
382 data_blob_clear_free(&password);
385 END_PROFILE(SMBtconX);
386 return ERROR_NT(nt_status);
390 server_devicetype = "IPC";
391 else if ( IS_PRINT(conn) )
392 server_devicetype = "LPT1:";
394 server_devicetype = "A:";
396 if (Protocol < PROTOCOL_NT1) {
397 set_message(outbuf,2,0,True);
399 p += srvstr_push(outbuf, p, server_devicetype, -1,
400 STR_TERMINATE|STR_ASCII);
401 set_message_end(outbuf,p);
403 /* NT sets the fstype of IPC$ to the null string */
404 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
406 set_message(outbuf,3,0,True);
409 p += srvstr_push(outbuf, p, server_devicetype, -1,
410 STR_TERMINATE|STR_ASCII);
411 p += srvstr_push(outbuf, p, fstype, -1,
414 set_message_end(outbuf,p);
416 /* what does setting this bit do? It is set by NT4 and
417 may affect the ability to autorun mounted cdroms */
418 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
419 (lp_csc_policy(SNUM(conn)) << 2));
421 init_dfsroot(conn, inbuf, outbuf);
425 DEBUG(3,("tconX service=%s \n",
428 /* set the incoming and outgoing tid to the just created one */
429 SSVAL(inbuf,smb_tid,conn->cnum);
430 SSVAL(outbuf,smb_tid,conn->cnum);
432 END_PROFILE(SMBtconX);
433 return chain_reply(inbuf,outbuf,length,bufsize);
436 /****************************************************************************
437 Reply to an unknown type.
438 ****************************************************************************/
440 int reply_unknown(char *inbuf,char *outbuf)
443 type = CVAL(inbuf,smb_com);
445 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
446 smb_fn_name(type), type, type));
448 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
451 /****************************************************************************
453 ****************************************************************************/
455 int reply_ioctl(connection_struct *conn,
456 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
458 uint16 device = SVAL(inbuf,smb_vwv1);
459 uint16 function = SVAL(inbuf,smb_vwv2);
460 uint32 ioctl_code = (device << 16) + function;
461 int replysize, outsize;
463 START_PROFILE(SMBioctl);
465 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
467 switch (ioctl_code) {
468 case IOCTL_QUERY_JOB_INFO:
472 END_PROFILE(SMBioctl);
473 return(ERROR_DOS(ERRSRV,ERRnosupport));
476 outsize = set_message(outbuf,8,replysize+1,True);
477 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
478 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
479 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
480 p = smb_buf(outbuf) + 1; /* Allow for alignment */
482 switch (ioctl_code) {
483 case IOCTL_QUERY_JOB_INFO:
485 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
487 END_PROFILE(SMBioctl);
488 return(UNIXERROR(ERRDOS,ERRbadfid));
490 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
491 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
493 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
499 END_PROFILE(SMBioctl);
503 /****************************************************************************
505 ****************************************************************************/
507 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
513 BOOL bad_path = False;
514 SMB_STRUCT_STAT sbuf;
517 START_PROFILE(SMBchkpth);
519 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
520 if (!NT_STATUS_IS_OK(status)) {
521 END_PROFILE(SMBchkpth);
522 return ERROR_NT(status);
525 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
527 unix_convert(name,conn,0,&bad_path,&sbuf);
529 mode = SVAL(inbuf,smb_vwv0);
531 if (check_name(name,conn)) {
532 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
533 if (!(ok = S_ISDIR(sbuf.st_mode))) {
534 END_PROFILE(SMBchkpth);
535 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
540 /* We special case this - as when a Windows machine
541 is parsing a path is steps through the components
542 one at a time - if a component fails it expects
543 ERRbadpath, not ERRbadfile.
545 if(errno == ENOENT) {
547 * Windows returns different error codes if
548 * the parent directory is valid but not the
549 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
550 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
551 * if the path is invalid.
554 END_PROFILE(SMBchkpth);
555 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
557 END_PROFILE(SMBchkpth);
558 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
560 } else if (errno == ENOTDIR) {
561 END_PROFILE(SMBchkpth);
562 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
565 END_PROFILE(SMBchkpth);
566 return(UNIXERROR(ERRDOS,ERRbadpath));
569 outsize = set_message(outbuf,0,0,True);
571 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
573 END_PROFILE(SMBchkpth);
577 /****************************************************************************
579 ****************************************************************************/
581 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
585 SMB_STRUCT_STAT sbuf;
590 BOOL bad_path = False;
594 START_PROFILE(SMBgetatr);
596 p = smb_buf(inbuf) + 1;
597 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
598 if (!NT_STATUS_IS_OK(status)) {
599 END_PROFILE(SMBgetatr);
600 return ERROR_NT(status);
603 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
605 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
606 under WfWg - weird! */
608 mode = aHIDDEN | aDIR;
609 if (!CAN_WRITE(conn))
615 unix_convert(fname,conn,0,&bad_path,&sbuf);
616 if (check_name(fname,conn)) {
617 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
618 mode = dos_mode(conn,fname,&sbuf);
620 mtime = sbuf.st_mtime;
625 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
631 END_PROFILE(SMBgetatr);
632 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
635 outsize = set_message(outbuf,10,0,True);
637 SSVAL(outbuf,smb_vwv0,mode);
638 if(lp_dos_filetime_resolution(SNUM(conn)) )
639 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
641 put_dos_date3(outbuf,smb_vwv1,mtime);
642 SIVAL(outbuf,smb_vwv3,(uint32)size);
644 if (Protocol >= PROTOCOL_NT1)
645 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
647 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
649 END_PROFILE(SMBgetatr);
653 /****************************************************************************
655 ****************************************************************************/
657 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
664 SMB_STRUCT_STAT sbuf;
665 BOOL bad_path = False;
669 START_PROFILE(SMBsetatr);
671 p = smb_buf(inbuf) + 1;
672 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
673 if (!NT_STATUS_IS_OK(status)) {
674 END_PROFILE(SMBsetatr);
675 return ERROR_NT(status);
678 unix_convert(fname,conn,0,&bad_path,&sbuf);
680 mode = SVAL(inbuf,smb_vwv0);
681 mtime = make_unix_date3(inbuf+smb_vwv1);
683 if (mode != FILE_ATTRIBUTE_NORMAL) {
684 if (VALID_STAT_OF_DIR(sbuf))
689 if (check_name(fname,conn)) {
690 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
697 ok = set_filetime(conn,fname,mtime);
700 END_PROFILE(SMBsetatr);
701 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
704 outsize = set_message(outbuf,0,0,True);
706 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
708 END_PROFILE(SMBsetatr);
712 /****************************************************************************
714 ****************************************************************************/
716 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
719 SMB_BIG_UINT dfree,dsize,bsize;
720 START_PROFILE(SMBdskattr);
722 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
724 outsize = set_message(outbuf,5,0,True);
726 if (Protocol <= PROTOCOL_LANMAN2) {
727 double total_space, free_space;
728 /* we need to scale this to a number that DOS6 can handle. We
729 use floating point so we can handle large drives on systems
730 that don't have 64 bit integers
732 we end up displaying a maximum of 2G to DOS systems
734 total_space = dsize * (double)bsize;
735 free_space = dfree * (double)bsize;
737 dsize = (total_space+63*512) / (64*512);
738 dfree = (free_space+63*512) / (64*512);
740 if (dsize > 0xFFFF) dsize = 0xFFFF;
741 if (dfree > 0xFFFF) dfree = 0xFFFF;
743 SSVAL(outbuf,smb_vwv0,dsize);
744 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
745 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
746 SSVAL(outbuf,smb_vwv3,dfree);
748 SSVAL(outbuf,smb_vwv0,dsize);
749 SSVAL(outbuf,smb_vwv1,bsize/512);
750 SSVAL(outbuf,smb_vwv2,512);
751 SSVAL(outbuf,smb_vwv3,dfree);
754 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
756 END_PROFILE(SMBdskattr);
760 /****************************************************************************
762 Can be called from SMBsearch, SMBffirst or SMBfunique.
763 ****************************************************************************/
765 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
775 unsigned int numentries = 0;
776 unsigned int maxentries = 0;
777 BOOL finished = False;
784 BOOL check_descend = False;
785 BOOL expect_close = False;
786 BOOL can_open = True;
787 BOOL bad_path = False;
789 START_PROFILE(SMBsearch);
791 *mask = *directory = *fname = 0;
793 /* If we were called as SMBffirst then we must expect close. */
794 if(CVAL(inbuf,smb_com) == SMBffirst)
797 outsize = set_message(outbuf,1,3,True);
798 maxentries = SVAL(inbuf,smb_vwv0);
799 dirtype = SVAL(inbuf,smb_vwv1);
800 p = smb_buf(inbuf) + 1;
801 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
802 if (!NT_STATUS_IS_OK(nt_status)) {
803 END_PROFILE(SMBsearch);
804 return ERROR_NT(nt_status);
807 status_len = SVAL(p, 0);
810 /* dirtype &= ~aDIR; */
812 if (status_len == 0) {
813 SMB_STRUCT_STAT sbuf;
816 pstrcpy(directory,path);
818 unix_convert(directory,conn,0,&bad_path,&sbuf);
821 if (!check_name(directory,conn))
824 p = strrchr_m(dir2,'/');
833 p = strrchr_m(directory,'/');
839 if (strlen(directory) == 0)
840 pstrcpy(directory,".");
841 memset((char *)status,'\0',21);
842 SCVAL(status,0,(dirtype & 0x1F));
847 status_dirtype = CVAL(status,0) & 0x1F;
848 if (status_dirtype != (dirtype & 0x1F))
849 dirtype = status_dirtype;
851 conn->dirptr = dptr_fetch(status+12,&dptr_num);
854 string_set(&conn->dirpath,dptr_path(dptr_num));
855 pstrcpy(mask, dptr_wcard(dptr_num));
859 p = smb_buf(outbuf) + 3;
862 if (status_len == 0) {
863 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
866 END_PROFILE(SMBsearch);
867 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
869 END_PROFILE(SMBsearch);
870 return ERROR_DOS(ERRDOS,ERRnofids);
872 dptr_set_wcard(dptr_num, strdup(mask));
873 dptr_set_attr(dptr_num, dirtype);
875 dirtype = dptr_attr(dptr_num);
878 DEBUG(4,("dptr_num is %d\n",dptr_num));
881 if ((dirtype&0x1F) == aVOLID) {
883 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
884 dptr_fill(p+12,dptr_num);
885 if (dptr_zero(p+12) && (status_len==0))
889 p += DIR_STRUCT_SIZE;
892 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
894 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
895 conn->dirpath,lp_dontdescend(SNUM(conn))));
896 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
897 check_descend = True;
899 for (i=numentries;(i<maxentries) && !finished;i++) {
900 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
903 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
904 dptr_fill(p+12,dptr_num);
907 p += DIR_STRUCT_SIZE;
916 /* If we were called as SMBffirst with smb_search_id == NULL
917 and no entries were found then return error and close dirptr
920 if(ok && expect_close && numentries == 0 && status_len == 0) {
921 if (Protocol < PROTOCOL_NT1) {
922 SCVAL(outbuf,smb_rcls,ERRDOS);
923 SSVAL(outbuf,smb_err,ERRnofiles);
925 /* Also close the dptr - we know it's gone */
926 dptr_close(&dptr_num);
927 } else if (numentries == 0 || !ok) {
928 if (Protocol < PROTOCOL_NT1) {
929 SCVAL(outbuf,smb_rcls,ERRDOS);
930 SSVAL(outbuf,smb_err,ERRnofiles);
932 dptr_close(&dptr_num);
935 /* If we were called as SMBfunique, then we can close the dirptr now ! */
936 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
937 dptr_close(&dptr_num);
939 SSVAL(outbuf,smb_vwv0,numentries);
940 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
941 SCVAL(smb_buf(outbuf),0,5);
942 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
944 if (Protocol >= PROTOCOL_NT1)
945 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
947 outsize += DIR_STRUCT_SIZE*numentries;
948 smb_setlen(outbuf,outsize - 4);
950 if ((! *directory) && dptr_path(dptr_num))
951 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
953 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
954 smb_fn_name(CVAL(inbuf,smb_com)),
955 mask, directory, dirtype, numentries, maxentries ) );
957 END_PROFILE(SMBsearch);
961 /****************************************************************************
962 Reply to a fclose (stop directory search).
963 ****************************************************************************/
965 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
975 START_PROFILE(SMBfclose);
977 outsize = set_message(outbuf,1,0,True);
978 p = smb_buf(inbuf) + 1;
979 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
980 if (!NT_STATUS_IS_OK(err)) {
981 END_PROFILE(SMBfclose);
982 return ERROR_NT(err);
985 status_len = SVAL(p,0);
988 if (status_len == 0) {
989 END_PROFILE(SMBfclose);
990 return ERROR_DOS(ERRSRV,ERRsrverror);
995 if(dptr_fetch(status+12,&dptr_num)) {
996 /* Close the dptr - we know it's gone */
997 dptr_close(&dptr_num);
1000 SSVAL(outbuf,smb_vwv0,0);
1002 DEBUG(3,("search close\n"));
1004 END_PROFILE(SMBfclose);
1008 /****************************************************************************
1010 ****************************************************************************/
1012 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1021 SMB_STRUCT_STAT sbuf;
1022 BOOL bad_path = False;
1024 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1025 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1027 START_PROFILE(SMBopen);
1029 share_mode = SVAL(inbuf,smb_vwv0);
1031 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 END_PROFILE(SMBopen);
1034 return ERROR_NT(status);
1037 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1039 unix_convert(fname,conn,0,&bad_path,&sbuf);
1041 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1042 (uint32)dos_attr, oplock_request,&rmode,NULL);
1045 END_PROFILE(SMBopen);
1046 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1047 /* We have re-scheduled this call. */
1048 clear_cached_errors();
1051 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1054 size = sbuf.st_size;
1055 fmode = dos_mode(conn,fname,&sbuf);
1056 mtime = sbuf.st_mtime;
1059 DEBUG(3,("attempt to open a directory %s\n",fname));
1060 close_file(fsp,False);
1061 END_PROFILE(SMBopen);
1062 return ERROR_DOS(ERRDOS,ERRnoaccess);
1065 outsize = set_message(outbuf,7,0,True);
1066 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1067 SSVAL(outbuf,smb_vwv1,fmode);
1068 if(lp_dos_filetime_resolution(SNUM(conn)) )
1069 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1071 put_dos_date3(outbuf,smb_vwv2,mtime);
1072 SIVAL(outbuf,smb_vwv4,(uint32)size);
1073 SSVAL(outbuf,smb_vwv6,rmode);
1075 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1076 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1078 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1079 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1080 END_PROFILE(SMBopen);
1084 /****************************************************************************
1085 Reply to an open and X.
1086 ****************************************************************************/
1088 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1091 int smb_mode = SVAL(inbuf,smb_vwv3);
1092 int smb_attr = SVAL(inbuf,smb_vwv5);
1093 /* Breakout the oplock request bits so we can set the
1094 reply bits separately. */
1095 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1096 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1097 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1099 int open_flags = SVAL(inbuf,smb_vwv2);
1100 int smb_sattr = SVAL(inbuf,smb_vwv4);
1101 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1103 int smb_ofun = SVAL(inbuf,smb_vwv8);
1105 int fmode=0,mtime=0,rmode=0;
1106 SMB_STRUCT_STAT sbuf;
1108 BOOL bad_path = False;
1111 START_PROFILE(SMBopenX);
1113 /* If it's an IPC, pass off the pipe handler. */
1115 if (lp_nt_pipe_support()) {
1116 END_PROFILE(SMBopenX);
1117 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1119 END_PROFILE(SMBopenX);
1120 return ERROR_DOS(ERRSRV,ERRaccess);
1124 /* XXXX we need to handle passed times, sattr and flags */
1125 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 END_PROFILE(SMBopenX);
1128 return ERROR_NT(status);
1131 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1133 unix_convert(fname,conn,0,&bad_path,&sbuf);
1135 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1136 oplock_request, &rmode,&smb_action);
1139 END_PROFILE(SMBopenX);
1140 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1141 /* We have re-scheduled this call. */
1142 clear_cached_errors();
1145 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1148 size = sbuf.st_size;
1149 fmode = dos_mode(conn,fname,&sbuf);
1150 mtime = sbuf.st_mtime;
1152 close_file(fsp,False);
1153 END_PROFILE(SMBopenX);
1154 return ERROR_DOS(ERRDOS,ERRnoaccess);
1157 /* If the caller set the extended oplock request bit
1158 and we granted one (by whatever means) - set the
1159 correct bit for extended oplock reply.
1162 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1163 smb_action |= EXTENDED_OPLOCK_GRANTED;
1165 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1166 smb_action |= EXTENDED_OPLOCK_GRANTED;
1168 /* If the caller set the core oplock request bit
1169 and we granted one (by whatever means) - set the
1170 correct bit for core oplock reply.
1173 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1174 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1176 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1177 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1179 set_message(outbuf,15,0,True);
1180 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1181 SSVAL(outbuf,smb_vwv3,fmode);
1182 if(lp_dos_filetime_resolution(SNUM(conn)) )
1183 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1185 put_dos_date3(outbuf,smb_vwv4,mtime);
1186 SIVAL(outbuf,smb_vwv6,(uint32)size);
1187 SSVAL(outbuf,smb_vwv8,rmode);
1188 SSVAL(outbuf,smb_vwv11,smb_action);
1190 END_PROFILE(SMBopenX);
1191 return chain_reply(inbuf,outbuf,length,bufsize);
1194 /****************************************************************************
1195 Reply to a SMBulogoffX.
1196 ****************************************************************************/
1198 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1200 uint16 vuid = SVAL(inbuf,smb_uid);
1201 user_struct *vuser = get_valid_user_struct(vuid);
1202 START_PROFILE(SMBulogoffX);
1205 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1207 /* in user level security we are supposed to close any files
1208 open by this user */
1209 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1210 file_close_user(vuid);
1212 invalidate_vuid(vuid);
1214 set_message(outbuf,2,0,True);
1216 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1218 END_PROFILE(SMBulogoffX);
1219 return chain_reply(inbuf,outbuf,length,bufsize);
1222 /****************************************************************************
1223 Reply to a mknew or a create.
1224 ****************************************************************************/
1226 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1233 BOOL bad_path = False;
1235 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1236 SMB_STRUCT_STAT sbuf;
1238 START_PROFILE(SMBcreate);
1240 com = SVAL(inbuf,smb_com);
1242 createmode = SVAL(inbuf,smb_vwv0);
1243 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 END_PROFILE(SMBcreate);
1246 return ERROR_NT(status);
1249 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1251 unix_convert(fname,conn,0,&bad_path,&sbuf);
1253 if (createmode & aVOLID)
1254 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1256 if(com == SMBmknew) {
1257 /* We should fail if file exists. */
1258 ofun = FILE_CREATE_IF_NOT_EXIST;
1260 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1261 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1264 /* Open file in dos compatibility share mode. */
1265 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1266 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1269 END_PROFILE(SMBcreate);
1270 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1271 /* We have re-scheduled this call. */
1272 clear_cached_errors();
1275 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1278 outsize = set_message(outbuf,1,0,True);
1279 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1281 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1282 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1284 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1285 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1287 DEBUG( 2, ( "new file %s\n", fname ) );
1288 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1290 END_PROFILE(SMBcreate);
1294 /****************************************************************************
1295 Reply to a create temporary file.
1296 ****************************************************************************/
1298 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1303 BOOL bad_path = False;
1305 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1307 SMB_STRUCT_STAT sbuf;
1310 unsigned int namelen;
1312 START_PROFILE(SMBctemp);
1314 createattr = SVAL(inbuf,smb_vwv0);
1315 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 END_PROFILE(SMBctemp);
1318 return ERROR_NT(status);
1321 pstrcat(fname,"/TMXXXXXX");
1323 pstrcat(fname,"TMXXXXXX");
1326 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1328 unix_convert(fname,conn,0,&bad_path,&sbuf);
1330 tmpfd = smb_mkstemp(fname);
1332 END_PROFILE(SMBctemp);
1333 return(UNIXERROR(ERRDOS,ERRnoaccess));
1336 SMB_VFS_STAT(conn,fname,&sbuf);
1338 /* Open file in dos compatibility share mode. */
1339 /* We should fail if file does not exist. */
1340 fsp = open_file_shared(conn,fname,&sbuf,
1341 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1342 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1343 (uint32)createattr, oplock_request, NULL, NULL);
1345 /* close fd from smb_mkstemp() */
1349 END_PROFILE(SMBctemp);
1350 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1351 /* We have re-scheduled this call. */
1352 clear_cached_errors();
1355 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1358 outsize = set_message(outbuf,1,0,True);
1359 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1361 /* the returned filename is relative to the directory */
1362 s = strrchr_m(fname, '/');
1368 p = smb_buf(outbuf);
1370 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1371 thing in the byte section. JRA */
1372 SSVALS(p, 0, -1); /* what is this? not in spec */
1374 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1376 outsize = set_message_end(outbuf, p);
1378 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1379 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1381 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1382 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1384 DEBUG( 2, ( "created temp file %s\n", fname ) );
1385 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1386 fname, fsp->fd, sbuf.st_mode ) );
1388 END_PROFILE(SMBctemp);
1392 /*******************************************************************
1393 Check if a user is allowed to rename a file.
1394 ********************************************************************/
1396 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1402 if (!CAN_WRITE(conn))
1403 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1405 if (S_ISDIR(pst->st_mode))
1406 return NT_STATUS_OK;
1408 /* We need a better way to return NT status codes from open... */
1412 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1413 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1416 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1417 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1418 ret = NT_STATUS_SHARING_VIOLATION;
1421 unix_ERR_ntstatus = NT_STATUS_OK;
1424 close_file(fsp,False);
1425 return NT_STATUS_OK;
1428 /*******************************************************************
1429 Check if a user is allowed to delete a file.
1430 ********************************************************************/
1432 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1434 SMB_STRUCT_STAT sbuf;
1440 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1443 if (!CAN_WRITE(conn))
1444 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1446 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1447 if(errno == ENOENT) {
1449 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1451 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1453 return map_nt_error_from_unix(errno);
1456 fmode = dos_mode(conn,fname,&sbuf);
1458 /* Can't delete a directory. */
1460 return NT_STATUS_FILE_IS_A_DIRECTORY;
1462 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1463 return NT_STATUS_OBJECT_NAME_INVALID;
1464 #endif /* JRATEST */
1466 if (!lp_delete_readonly(SNUM(conn))) {
1468 return NT_STATUS_CANNOT_DELETE;
1470 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1471 return NT_STATUS_NO_SUCH_FILE;
1473 /* We need a better way to return NT status codes from open... */
1477 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1478 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1481 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1482 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1483 ret = unix_ERR_ntstatus;
1484 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1485 ret = NT_STATUS_SHARING_VIOLATION;
1488 unix_ERR_ntstatus = NT_STATUS_OK;
1491 close_file(fsp,False);
1492 return NT_STATUS_OK;
1495 /****************************************************************************
1496 The guts of the unlink command, split out so it may be called by the NT SMB
1498 ****************************************************************************/
1500 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1506 NTSTATUS error = NT_STATUS_OK;
1508 BOOL bad_path = False;
1510 SMB_STRUCT_STAT sbuf;
1512 *directory = *mask = 0;
1514 /* We must check for wildcards in the name given
1515 * directly by the client - before any unmangling.
1516 * This prevents an unmangling of a UNIX name containing
1517 * a DOS wildcard like '*' or '?' from unmangling into
1518 * a wildcard delete which was not intended.
1519 * FIX for #226. JRA.
1522 has_wild = ms_has_wild(name);
1524 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1526 p = strrchr_m(name,'/');
1528 pstrcpy(directory,".");
1532 pstrcpy(directory,name);
1537 * We should only check the mangled cache
1538 * here if unix_convert failed. This means
1539 * that the path in 'mask' doesn't exist
1540 * on the file system and so we need to look
1541 * for a possible mangle. This patch from
1542 * Tine Smukavec <valentin.smukavec@hermes.si>.
1545 if (!rc && mangle_is_mangled(mask))
1546 mangle_check_cache( mask );
1549 pstrcat(directory,"/");
1550 pstrcat(directory,mask);
1551 error = can_delete(directory,conn,dirtype,bad_path);
1552 if (!NT_STATUS_IS_OK(error))
1555 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1559 void *dirptr = NULL;
1562 if (check_name(directory,conn))
1563 dirptr = OpenDir(conn, directory, True);
1565 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1566 the pattern matches against the long name, otherwise the short name
1567 We don't implement this yet XXXX
1571 error = NT_STATUS_NO_SUCH_FILE;
1573 if (strequal(mask,"????????.???"))
1576 while ((dname = ReadDirName(dirptr))) {
1578 BOOL sys_direntry = False;
1579 pstrcpy(fname,dname);
1581 /* Quick check for "." and ".." */
1582 if (fname[0] == '.') {
1583 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1584 if ((dirtype & aDIR)) {
1585 sys_direntry = True;
1592 if(!mask_match(fname, mask, conn->case_sensitive))
1596 error = NT_STATUS_OBJECT_NAME_INVALID;
1600 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1601 error = can_delete(fname,conn,dirtype,bad_path);
1602 if (!NT_STATUS_IS_OK(error)) {
1605 if (SMB_VFS_UNLINK(conn,fname) == 0)
1607 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1613 if (count == 0 && NT_STATUS_IS_OK(error)) {
1614 error = map_nt_error_from_unix(errno);
1620 /****************************************************************************
1622 ****************************************************************************/
1624 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1631 START_PROFILE(SMBunlink);
1633 dirtype = SVAL(inbuf,smb_vwv0);
1635 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 END_PROFILE(SMBunlink);
1638 return ERROR_NT(status);
1641 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1643 DEBUG(3,("reply_unlink : %s\n",name));
1645 status = unlink_internals(conn, dirtype, name);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1648 /* We have re-scheduled this call. */
1649 clear_cached_errors();
1652 return ERROR_NT(status);
1656 * Win2k needs a changenotify request response before it will
1657 * update after a rename..
1659 process_pending_change_notify_queue((time_t)0);
1661 outsize = set_message(outbuf,0,0,True);
1663 END_PROFILE(SMBunlink);
1667 /****************************************************************************
1669 ****************************************************************************/
1671 void fail_readraw(void)
1674 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1676 exit_server(errstr);
1679 /****************************************************************************
1680 Use sendfile in readbraw.
1681 ****************************************************************************/
1683 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1684 ssize_t mincount, char *outbuf)
1688 #if defined(WITH_SENDFILE)
1690 * We can only use sendfile on a non-chained packet and on a file
1691 * that is exclusively oplocked. reply_readbraw has already checked the length.
1694 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1695 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1698 _smb_setlen(outbuf,nread);
1699 header.data = outbuf;
1703 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1705 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1706 * return ENOSYS then pretend we just got a normal read.
1708 if (errno == ENOSYS)
1711 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1712 fsp->fsp_name, strerror(errno) ));
1713 exit_server("send_file_readbraw sendfile failed");
1722 ret = read_file(fsp,outbuf+4,startpos,nread);
1723 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1732 _smb_setlen(outbuf,ret);
1733 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1737 /****************************************************************************
1738 Reply to a readbraw (core+ protocol).
1739 ****************************************************************************/
1741 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1743 extern struct current_user current_user;
1744 ssize_t maxcount,mincount;
1747 char *header = outbuf;
1749 START_PROFILE(SMBreadbraw);
1751 if (srv_is_signing_active()) {
1752 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1756 * Special check if an oplock break has been issued
1757 * and the readraw request croses on the wire, we must
1758 * return a zero length response here.
1761 if(global_oplock_break) {
1762 _smb_setlen(header,0);
1763 if (write_data(smbd_server_fd(),header,4) != 4)
1765 DEBUG(5,("readbraw - oplock break finished\n"));
1766 END_PROFILE(SMBreadbraw);
1770 fsp = file_fsp(inbuf,smb_vwv0);
1772 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1774 * fsp could be NULL here so use the value from the packet. JRA.
1776 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1777 _smb_setlen(header,0);
1778 if (write_data(smbd_server_fd(),header,4) != 4)
1780 END_PROFILE(SMBreadbraw);
1784 CHECK_FSP(fsp,conn);
1786 flush_write_cache(fsp, READRAW_FLUSH);
1788 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1789 if(CVAL(inbuf,smb_wct) == 10) {
1791 * This is a large offset (64 bit) read.
1793 #ifdef LARGE_SMB_OFF_T
1795 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1797 #else /* !LARGE_SMB_OFF_T */
1800 * Ensure we haven't been sent a >32 bit offset.
1803 if(IVAL(inbuf,smb_vwv8) != 0) {
1804 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1805 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1806 _smb_setlen(header,0);
1807 if (write_data(smbd_server_fd(),header,4) != 4)
1809 END_PROFILE(SMBreadbraw);
1813 #endif /* LARGE_SMB_OFF_T */
1816 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1817 _smb_setlen(header,0);
1818 if (write_data(smbd_server_fd(),header,4) != 4)
1820 END_PROFILE(SMBreadbraw);
1824 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1825 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1827 /* ensure we don't overrun the packet size */
1828 maxcount = MIN(65535,maxcount);
1830 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1831 SMB_OFF_T size = fsp->size;
1832 SMB_OFF_T sizeneeded = startpos + maxcount;
1834 if (size < sizeneeded) {
1836 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1838 if (!fsp->can_write)
1842 if (startpos >= size)
1845 nread = MIN(maxcount,(size - startpos));
1848 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1849 if (nread < mincount)
1853 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1854 (int)maxcount, (int)mincount, (int)nread ) );
1856 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1858 DEBUG(5,("readbraw finished\n"));
1859 END_PROFILE(SMBreadbraw);
1863 /****************************************************************************
1864 Reply to a lockread (core+ protocol).
1865 ****************************************************************************/
1867 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1875 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1876 BOOL my_lock_ctx = False;
1877 START_PROFILE(SMBlockread);
1879 CHECK_FSP(fsp,conn);
1882 release_level_2_oplocks_on_change(fsp);
1884 numtoread = SVAL(inbuf,smb_vwv1);
1885 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1887 outsize = set_message(outbuf,5,3,True);
1888 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1889 data = smb_buf(outbuf) + 3;
1892 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1893 * protocol request that predates the read/write lock concept.
1894 * Thus instead of asking for a read lock here we need to ask
1895 * for a write lock. JRA.
1896 * Note that the requested lock size is unaffected by max_recv.
1899 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1900 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1902 if (NT_STATUS_V(status)) {
1905 * We used to make lockread a blocking lock. It turns out
1906 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1910 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1912 * A blocking lock was requested. Package up
1913 * this smb into a queued request and push it
1914 * onto the blocking lock queue.
1916 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1917 (SMB_BIG_UINT)numtoread)) {
1918 END_PROFILE(SMBlockread);
1923 END_PROFILE(SMBlockread);
1924 return ERROR_NT(status);
1928 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1931 if (numtoread > max_recv) {
1932 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1933 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1934 (unsigned int)numtoread, (unsigned int)max_recv ));
1935 numtoread = MIN(numtoread,max_recv);
1937 nread = read_file(fsp,data,startpos,numtoread);
1940 END_PROFILE(SMBlockread);
1941 return(UNIXERROR(ERRDOS,ERRnoaccess));
1945 SSVAL(outbuf,smb_vwv0,nread);
1946 SSVAL(outbuf,smb_vwv5,nread+3);
1947 SSVAL(smb_buf(outbuf),1,nread);
1949 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1950 fsp->fnum, (int)numtoread, (int)nread));
1952 END_PROFILE(SMBlockread);
1956 /****************************************************************************
1958 ****************************************************************************/
1960 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1967 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1968 START_PROFILE(SMBread);
1970 CHECK_FSP(fsp,conn);
1973 numtoread = SVAL(inbuf,smb_vwv1);
1974 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1976 outsize = set_message(outbuf,5,3,True);
1977 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1979 * The requested read size cannot be greater than max_recv. JRA.
1981 if (numtoread > max_recv) {
1982 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1983 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1984 (unsigned int)numtoread, (unsigned int)max_recv ));
1985 numtoread = MIN(numtoread,max_recv);
1988 data = smb_buf(outbuf) + 3;
1990 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1991 END_PROFILE(SMBread);
1992 return ERROR_DOS(ERRDOS,ERRlock);
1996 nread = read_file(fsp,data,startpos,numtoread);
1999 END_PROFILE(SMBread);
2000 return(UNIXERROR(ERRDOS,ERRnoaccess));
2004 SSVAL(outbuf,smb_vwv0,nread);
2005 SSVAL(outbuf,smb_vwv5,nread+3);
2006 SCVAL(smb_buf(outbuf),0,1);
2007 SSVAL(smb_buf(outbuf),1,nread);
2009 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2010 fsp->fnum, (int)numtoread, (int)nread ) );
2012 END_PROFILE(SMBread);
2016 /****************************************************************************
2017 Reply to a read and X - possibly using sendfile.
2018 ****************************************************************************/
2020 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
2021 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2024 char *data = smb_buf(outbuf);
2026 #if defined(WITH_SENDFILE)
2028 * We can only use sendfile on a non-chained packet and on a file
2029 * that is exclusively oplocked.
2032 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2033 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2034 SMB_STRUCT_STAT sbuf;
2037 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2038 return(UNIXERROR(ERRDOS,ERRnoaccess));
2040 if (startpos > sbuf.st_size)
2043 if (smb_maxcnt > (sbuf.st_size - startpos))
2044 smb_maxcnt = (sbuf.st_size - startpos);
2046 if (smb_maxcnt == 0)
2050 * Set up the packet header before send. We
2051 * assume here the sendfile will work (get the
2052 * correct amount of data).
2055 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2056 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2057 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2058 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2059 SCVAL(outbuf,smb_vwv0,0xFF);
2060 set_message(outbuf,12,smb_maxcnt,False);
2061 header.data = outbuf;
2062 header.length = data - outbuf;
2065 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2067 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2068 * return ENOSYS then pretend we just got a normal read.
2070 if (errno == ENOSYS)
2073 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2074 fsp->fsp_name, strerror(errno) ));
2075 exit_server("send_file_readX sendfile failed");
2078 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2079 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2087 nread = read_file(fsp,data,startpos,smb_maxcnt);
2090 END_PROFILE(SMBreadX);
2091 return(UNIXERROR(ERRDOS,ERRnoaccess));
2094 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2095 SSVAL(outbuf,smb_vwv5,nread);
2096 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2097 SSVAL(smb_buf(outbuf),-2,nread);
2099 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2100 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2105 /****************************************************************************
2106 Reply to a read and X.
2107 ****************************************************************************/
2109 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2111 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2112 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2114 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2116 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2119 START_PROFILE(SMBreadX);
2121 /* If it's an IPC, pass off the pipe handler. */
2123 END_PROFILE(SMBreadX);
2124 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2127 CHECK_FSP(fsp,conn);
2130 set_message(outbuf,12,0,True);
2132 if(CVAL(inbuf,smb_wct) == 12) {
2133 #ifdef LARGE_SMB_OFF_T
2135 * This is a large offset (64 bit) read.
2137 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2139 #else /* !LARGE_SMB_OFF_T */
2142 * Ensure we haven't been sent a >32 bit offset.
2145 if(IVAL(inbuf,smb_vwv10) != 0) {
2146 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2147 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2148 END_PROFILE(SMBreadX);
2149 return ERROR_DOS(ERRDOS,ERRbadaccess);
2152 #endif /* LARGE_SMB_OFF_T */
2156 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2157 END_PROFILE(SMBreadX);
2158 return ERROR_DOS(ERRDOS,ERRlock);
2161 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2163 nread = chain_reply(inbuf,outbuf,length,bufsize);
2165 END_PROFILE(SMBreadX);
2169 /****************************************************************************
2170 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2171 ****************************************************************************/
2173 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2176 ssize_t total_written=0;
2177 size_t numtowrite=0;
2182 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2184 START_PROFILE(SMBwritebraw);
2186 if (srv_is_signing_active()) {
2187 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2190 CHECK_FSP(fsp,conn);
2193 tcount = IVAL(inbuf,smb_vwv1);
2194 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2195 write_through = BITSETW(inbuf+smb_vwv7,0);
2197 /* We have to deal with slightly different formats depending
2198 on whether we are using the core+ or lanman1.0 protocol */
2200 if(Protocol <= PROTOCOL_COREPLUS) {
2201 numtowrite = SVAL(smb_buf(inbuf),-2);
2202 data = smb_buf(inbuf);
2204 numtowrite = SVAL(inbuf,smb_vwv10);
2205 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2208 /* force the error type */
2209 SCVAL(inbuf,smb_com,SMBwritec);
2210 SCVAL(outbuf,smb_com,SMBwritec);
2212 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2213 END_PROFILE(SMBwritebraw);
2214 return(ERROR_DOS(ERRDOS,ERRlock));
2218 nwritten = write_file(fsp,data,startpos,numtowrite);
2220 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2221 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2223 if (nwritten < (ssize_t)numtowrite) {
2224 END_PROFILE(SMBwritebraw);
2225 return(UNIXERROR(ERRHRD,ERRdiskfull));
2228 total_written = nwritten;
2230 /* Return a message to the redirector to tell it to send more bytes */
2231 SCVAL(outbuf,smb_com,SMBwritebraw);
2232 SSVALS(outbuf,smb_vwv0,-1);
2233 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2234 if (!send_smb(smbd_server_fd(),outbuf))
2235 exit_server("reply_writebraw: send_smb failed.");
2237 /* Now read the raw data into the buffer and write it */
2238 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2239 exit_server("secondary writebraw failed");
2242 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2243 numtowrite = smb_len(inbuf);
2245 /* Set up outbuf to return the correct return */
2246 outsize = set_message(outbuf,1,0,True);
2247 SCVAL(outbuf,smb_com,SMBwritec);
2248 SSVAL(outbuf,smb_vwv0,total_written);
2250 if (numtowrite != 0) {
2252 if (numtowrite > BUFFER_SIZE) {
2253 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2254 (unsigned int)numtowrite ));
2255 exit_server("secondary writebraw failed");
2258 if (tcount > nwritten+numtowrite) {
2259 DEBUG(3,("Client overestimated the write %d %d %d\n",
2260 (int)tcount,(int)nwritten,(int)numtowrite));
2263 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2264 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2266 exit_server("secondary writebraw failed");
2269 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2271 if (nwritten < (ssize_t)numtowrite) {
2272 SCVAL(outbuf,smb_rcls,ERRHRD);
2273 SSVAL(outbuf,smb_err,ERRdiskfull);
2277 total_written += nwritten;
2280 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2281 sync_file(conn,fsp);
2283 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2284 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2286 /* we won't return a status if write through is not selected - this follows what WfWg does */
2287 END_PROFILE(SMBwritebraw);
2288 if (!write_through && total_written==tcount) {
2290 #if RABBIT_PELLET_FIX
2292 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2293 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2295 if (!send_keepalive(smbd_server_fd()))
2296 exit_server("reply_writebraw: send of keepalive failed");
2304 /****************************************************************************
2305 Reply to a writeunlock (core+).
2306 ****************************************************************************/
2308 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2309 int size, int dum_buffsize)
2311 ssize_t nwritten = -1;
2315 NTSTATUS status = NT_STATUS_OK;
2316 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2318 START_PROFILE(SMBwriteunlock);
2320 CHECK_FSP(fsp,conn);
2323 numtowrite = SVAL(inbuf,smb_vwv1);
2324 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2325 data = smb_buf(inbuf) + 3;
2327 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2328 WRITE_LOCK,False)) {
2329 END_PROFILE(SMBwriteunlock);
2330 return ERROR_DOS(ERRDOS,ERRlock);
2333 /* The special X/Open SMB protocol handling of
2334 zero length writes is *NOT* done for
2339 nwritten = write_file(fsp,data,startpos,numtowrite);
2341 if (lp_syncalways(SNUM(conn)))
2342 sync_file(conn,fsp);
2344 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2345 END_PROFILE(SMBwriteunlock);
2346 return(UNIXERROR(ERRHRD,ERRdiskfull));
2350 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2351 (SMB_BIG_UINT)startpos);
2352 if (NT_STATUS_V(status)) {
2353 END_PROFILE(SMBwriteunlock);
2354 return ERROR_NT(status);
2358 outsize = set_message(outbuf,1,0,True);
2360 SSVAL(outbuf,smb_vwv0,nwritten);
2362 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2363 fsp->fnum, (int)numtowrite, (int)nwritten));
2365 END_PROFILE(SMBwriteunlock);
2369 /****************************************************************************
2371 ****************************************************************************/
2373 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2376 ssize_t nwritten = -1;
2379 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2381 START_PROFILE(SMBwrite);
2383 /* If it's an IPC, pass off the pipe handler. */
2385 END_PROFILE(SMBwrite);
2386 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2389 CHECK_FSP(fsp,conn);
2392 numtowrite = SVAL(inbuf,smb_vwv1);
2393 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2394 data = smb_buf(inbuf) + 3;
2396 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2397 END_PROFILE(SMBwrite);
2398 return ERROR_DOS(ERRDOS,ERRlock);
2402 * X/Open SMB protocol says that if smb_vwv1 is
2403 * zero then the file size should be extended or
2404 * truncated to the size given in smb_vwv[2-3].
2407 if(numtowrite == 0) {
2409 * This is actually an allocate call, and set EOF. JRA.
2411 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2413 END_PROFILE(SMBwrite);
2414 return ERROR_NT(NT_STATUS_DISK_FULL);
2416 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2418 END_PROFILE(SMBwrite);
2419 return ERROR_NT(NT_STATUS_DISK_FULL);
2422 nwritten = write_file(fsp,data,startpos,numtowrite);
2424 if (lp_syncalways(SNUM(conn)))
2425 sync_file(conn,fsp);
2427 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2428 END_PROFILE(SMBwrite);
2429 return(UNIXERROR(ERRHRD,ERRdiskfull));
2432 outsize = set_message(outbuf,1,0,True);
2434 SSVAL(outbuf,smb_vwv0,nwritten);
2436 if (nwritten < (ssize_t)numtowrite) {
2437 SCVAL(outbuf,smb_rcls,ERRHRD);
2438 SSVAL(outbuf,smb_err,ERRdiskfull);
2441 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2443 END_PROFILE(SMBwrite);
2447 /****************************************************************************
2448 Reply to a write and X.
2449 ****************************************************************************/
2451 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2453 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2454 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2455 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2456 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2457 ssize_t nwritten = -1;
2458 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2459 unsigned int smblen = smb_len(inbuf);
2461 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2462 START_PROFILE(SMBwriteX);
2464 /* If it's an IPC, pass off the pipe handler. */
2466 END_PROFILE(SMBwriteX);
2467 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2470 CHECK_FSP(fsp,conn);
2473 /* Deal with possible LARGE_WRITEX */
2475 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2477 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2478 END_PROFILE(SMBwriteX);
2479 return ERROR_DOS(ERRDOS,ERRbadmem);
2482 data = smb_base(inbuf) + smb_doff;
2484 if(CVAL(inbuf,smb_wct) == 14) {
2485 #ifdef LARGE_SMB_OFF_T
2487 * This is a large offset (64 bit) write.
2489 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2491 #else /* !LARGE_SMB_OFF_T */
2494 * Ensure we haven't been sent a >32 bit offset.
2497 if(IVAL(inbuf,smb_vwv12) != 0) {
2498 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2499 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2500 END_PROFILE(SMBwriteX);
2501 return ERROR_DOS(ERRDOS,ERRbadaccess);
2504 #endif /* LARGE_SMB_OFF_T */
2507 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2508 END_PROFILE(SMBwriteX);
2509 return ERROR_DOS(ERRDOS,ERRlock);
2512 /* X/Open SMB protocol says that, unlike SMBwrite
2513 if the length is zero then NO truncation is
2514 done, just a write of zero. To truncate a file,
2520 nwritten = write_file(fsp,data,startpos,numtowrite);
2522 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2523 END_PROFILE(SMBwriteX);
2524 return(UNIXERROR(ERRHRD,ERRdiskfull));
2527 set_message(outbuf,6,0,True);
2529 SSVAL(outbuf,smb_vwv2,nwritten);
2531 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2533 if (nwritten < (ssize_t)numtowrite) {
2534 SCVAL(outbuf,smb_rcls,ERRHRD);
2535 SSVAL(outbuf,smb_err,ERRdiskfull);
2538 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2539 fsp->fnum, (int)numtowrite, (int)nwritten));
2541 if (lp_syncalways(SNUM(conn)) || write_through)
2542 sync_file(conn,fsp);
2544 END_PROFILE(SMBwriteX);
2545 return chain_reply(inbuf,outbuf,length,bufsize);
2548 /****************************************************************************
2550 ****************************************************************************/
2552 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2558 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2559 START_PROFILE(SMBlseek);
2561 CHECK_FSP(fsp,conn);
2563 flush_write_cache(fsp, SEEK_FLUSH);
2565 mode = SVAL(inbuf,smb_vwv1) & 3;
2566 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2567 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2576 res = fsp->pos + startpos;
2587 if (umode == SEEK_END) {
2588 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2589 if(errno == EINVAL) {
2590 SMB_OFF_T current_pos = startpos;
2591 SMB_STRUCT_STAT sbuf;
2593 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2594 END_PROFILE(SMBlseek);
2595 return(UNIXERROR(ERRDOS,ERRnoaccess));
2598 current_pos += sbuf.st_size;
2600 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2605 END_PROFILE(SMBlseek);
2606 return(UNIXERROR(ERRDOS,ERRnoaccess));
2612 outsize = set_message(outbuf,2,0,True);
2613 SIVAL(outbuf,smb_vwv0,res);
2615 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2616 fsp->fnum, (double)startpos, (double)res, mode));
2618 END_PROFILE(SMBlseek);
2622 /****************************************************************************
2624 ****************************************************************************/
2626 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2628 int outsize = set_message(outbuf,0,0,True);
2629 uint16 fnum = SVAL(inbuf,smb_vwv0);
2630 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2631 START_PROFILE(SMBflush);
2634 CHECK_FSP(fsp,conn);
2637 file_sync_all(conn);
2639 sync_file(conn,fsp);
2642 DEBUG(3,("flush\n"));
2643 END_PROFILE(SMBflush);
2647 /****************************************************************************
2649 ****************************************************************************/
2651 int reply_exit(connection_struct *conn,
2652 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2655 START_PROFILE(SMBexit);
2657 file_close_pid(SVAL(inbuf,smb_pid));
2659 outsize = set_message(outbuf,0,0,True);
2661 DEBUG(3,("exit\n"));
2663 END_PROFILE(SMBexit);
2667 /****************************************************************************
2668 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2669 ****************************************************************************/
2671 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2674 extern struct current_user current_user;
2677 int32 eclass = 0, err = 0;
2678 files_struct *fsp = NULL;
2679 START_PROFILE(SMBclose);
2681 outsize = set_message(outbuf,0,0,True);
2683 /* If it's an IPC, pass off to the pipe handler. */
2685 END_PROFILE(SMBclose);
2686 return reply_pipe_close(conn, inbuf,outbuf);
2689 fsp = file_fsp(inbuf,smb_vwv0);
2692 * We can only use CHECK_FSP if we know it's not a directory.
2695 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2696 END_PROFILE(SMBclose);
2697 return ERROR_DOS(ERRDOS,ERRbadfid);
2700 if(fsp->is_directory) {
2702 * Special case - close NT SMB directory handle.
2704 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2705 close_file(fsp,True);
2708 * Close ordinary file.
2713 /* Save the name for time set in close. */
2714 pstrcpy( file_name, fsp->fsp_name);
2716 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2718 conn->num_files_open));
2721 * close_file() returns the unix errno if an error
2722 * was detected on close - normally this is due to
2723 * a disk full error. If not then it was probably an I/O error.
2726 if((close_err = close_file(fsp,True)) != 0) {
2728 END_PROFILE(SMBclose);
2729 return (UNIXERROR(ERRHRD,ERRgeneral));
2733 * Now take care of any time sent in the close.
2736 mtime = make_unix_date3(inbuf+smb_vwv1);
2738 /* try and set the date */
2739 set_filetime(conn, file_name, mtime);
2743 /* We have a cached error */
2745 END_PROFILE(SMBclose);
2746 return ERROR_DOS(eclass,err);
2749 END_PROFILE(SMBclose);
2753 /****************************************************************************
2754 Reply to a writeclose (Core+ protocol).
2755 ****************************************************************************/
2757 int reply_writeclose(connection_struct *conn,
2758 char *inbuf,char *outbuf, int size, int dum_buffsize)
2761 ssize_t nwritten = -1;
2767 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2768 START_PROFILE(SMBwriteclose);
2770 CHECK_FSP(fsp,conn);
2773 numtowrite = SVAL(inbuf,smb_vwv1);
2774 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2775 mtime = make_unix_date3(inbuf+smb_vwv4);
2776 data = smb_buf(inbuf) + 1;
2778 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2779 END_PROFILE(SMBwriteclose);
2780 return ERROR_DOS(ERRDOS,ERRlock);
2783 nwritten = write_file(fsp,data,startpos,numtowrite);
2785 set_filetime(conn, fsp->fsp_name,mtime);
2788 * More insanity. W2K only closes the file if writelen > 0.
2793 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2795 close_err = close_file(fsp,True);
2798 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2799 fsp->fnum, (int)numtowrite, (int)nwritten,
2800 conn->num_files_open));
2802 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2803 END_PROFILE(SMBwriteclose);
2804 return(UNIXERROR(ERRHRD,ERRdiskfull));
2807 if(close_err != 0) {
2809 END_PROFILE(SMBwriteclose);
2810 return(UNIXERROR(ERRHRD,ERRgeneral));
2813 outsize = set_message(outbuf,1,0,True);
2815 SSVAL(outbuf,smb_vwv0,nwritten);
2816 END_PROFILE(SMBwriteclose);
2820 /****************************************************************************
2822 ****************************************************************************/
2824 int reply_lock(connection_struct *conn,
2825 char *inbuf,char *outbuf, int length, int dum_buffsize)
2827 int outsize = set_message(outbuf,0,0,True);
2828 SMB_BIG_UINT count,offset;
2830 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2831 BOOL my_lock_ctx = False;
2833 START_PROFILE(SMBlock);
2835 CHECK_FSP(fsp,conn);
2837 release_level_2_oplocks_on_change(fsp);
2839 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2840 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2842 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2843 fsp->fd, fsp->fnum, (double)offset, (double)count));
2845 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2846 if (NT_STATUS_V(status)) {
2848 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2849 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2851 * A blocking lock was requested. Package up
2852 * this smb into a queued request and push it
2853 * onto the blocking lock queue.
2855 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2856 END_PROFILE(SMBlock);
2861 END_PROFILE(SMBlock);
2862 return ERROR_NT(status);
2865 END_PROFILE(SMBlock);
2869 /****************************************************************************
2871 ****************************************************************************/
2873 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2876 int outsize = set_message(outbuf,0,0,True);
2877 SMB_BIG_UINT count,offset;
2879 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2880 START_PROFILE(SMBunlock);
2882 CHECK_FSP(fsp,conn);
2884 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2885 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2887 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2888 if (NT_STATUS_V(status)) {
2889 END_PROFILE(SMBunlock);
2890 return ERROR_NT(status);
2893 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2894 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2896 END_PROFILE(SMBunlock);
2900 /****************************************************************************
2902 ****************************************************************************/
2904 int reply_tdis(connection_struct *conn,
2905 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2907 int outsize = set_message(outbuf,0,0,True);
2909 START_PROFILE(SMBtdis);
2911 vuid = SVAL(inbuf,smb_uid);
2914 DEBUG(4,("Invalid connection in tdis\n"));
2915 END_PROFILE(SMBtdis);
2916 return ERROR_DOS(ERRSRV,ERRinvnid);
2921 close_cnum(conn,vuid);
2923 END_PROFILE(SMBtdis);
2927 /****************************************************************************
2929 ****************************************************************************/
2931 int reply_echo(connection_struct *conn,
2932 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2934 int smb_reverb = SVAL(inbuf,smb_vwv0);
2936 unsigned int data_len = smb_buflen(inbuf);
2937 int outsize = set_message(outbuf,1,data_len,True);
2938 START_PROFILE(SMBecho);
2940 if (data_len > BUFFER_SIZE) {
2941 DEBUG(0,("reply_echo: data_len too large.\n"));
2942 END_PROFILE(SMBecho);
2946 /* copy any incoming data back out */
2948 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2950 if (smb_reverb > 100) {
2951 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2955 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2956 SSVAL(outbuf,smb_vwv0,seq_num);
2958 smb_setlen(outbuf,outsize - 4);
2960 if (!send_smb(smbd_server_fd(),outbuf))
2961 exit_server("reply_echo: send_smb failed.");
2964 DEBUG(3,("echo %d times\n", smb_reverb));
2968 END_PROFILE(SMBecho);
2972 /****************************************************************************
2973 Reply to a printopen.
2974 ****************************************************************************/
2976 int reply_printopen(connection_struct *conn,
2977 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2981 START_PROFILE(SMBsplopen);
2983 if (!CAN_PRINT(conn)) {
2984 END_PROFILE(SMBsplopen);
2985 return ERROR_DOS(ERRDOS,ERRnoaccess);
2988 /* Open for exclusive use, write only. */
2989 fsp = print_fsp_open(conn, NULL);
2992 END_PROFILE(SMBsplopen);
2993 return(UNIXERROR(ERRDOS,ERRnoaccess));
2996 outsize = set_message(outbuf,1,0,True);
2997 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2999 DEBUG(3,("openprint fd=%d fnum=%d\n",
3000 fsp->fd, fsp->fnum));
3002 END_PROFILE(SMBsplopen);
3006 /****************************************************************************
3007 Reply to a printclose.
3008 ****************************************************************************/
3010 int reply_printclose(connection_struct *conn,
3011 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3013 int outsize = set_message(outbuf,0,0,True);
3014 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3016 START_PROFILE(SMBsplclose);
3018 CHECK_FSP(fsp,conn);
3020 if (!CAN_PRINT(conn)) {
3021 END_PROFILE(SMBsplclose);
3022 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3025 DEBUG(3,("printclose fd=%d fnum=%d\n",
3026 fsp->fd,fsp->fnum));
3028 close_err = close_file(fsp,True);
3030 if(close_err != 0) {
3032 END_PROFILE(SMBsplclose);
3033 return(UNIXERROR(ERRHRD,ERRgeneral));
3036 END_PROFILE(SMBsplclose);
3040 /****************************************************************************
3041 Reply to a printqueue.
3042 ****************************************************************************/
3044 int reply_printqueue(connection_struct *conn,
3045 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3047 int outsize = set_message(outbuf,2,3,True);
3048 int max_count = SVAL(inbuf,smb_vwv0);
3049 int start_index = SVAL(inbuf,smb_vwv1);
3050 START_PROFILE(SMBsplretq);
3052 /* we used to allow the client to get the cnum wrong, but that
3053 is really quite gross and only worked when there was only
3054 one printer - I think we should now only accept it if they
3055 get it right (tridge) */
3056 if (!CAN_PRINT(conn)) {
3057 END_PROFILE(SMBsplretq);
3058 return ERROR_DOS(ERRDOS,ERRnoaccess);
3061 SSVAL(outbuf,smb_vwv0,0);
3062 SSVAL(outbuf,smb_vwv1,0);
3063 SCVAL(smb_buf(outbuf),0,1);
3064 SSVAL(smb_buf(outbuf),1,0);
3066 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3067 start_index, max_count));
3070 print_queue_struct *queue = NULL;
3071 print_status_struct status;
3072 char *p = smb_buf(outbuf) + 3;
3073 int count = print_queue_status(SNUM(conn), &queue, &status);
3074 int num_to_get = ABS(max_count);
3075 int first = (max_count>0?start_index:start_index+max_count+1);
3081 num_to_get = MIN(num_to_get,count-first);
3084 for (i=first;i<first+num_to_get;i++) {
3085 put_dos_date2(p,0,queue[i].time);
3086 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3087 SSVAL(p,5, queue[i].job);
3088 SIVAL(p,7,queue[i].size);
3090 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3095 outsize = set_message(outbuf,2,28*count+3,False);
3096 SSVAL(outbuf,smb_vwv0,count);
3097 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3098 SCVAL(smb_buf(outbuf),0,1);
3099 SSVAL(smb_buf(outbuf),1,28*count);
3104 DEBUG(3,("%d entries returned in queue\n",count));
3107 END_PROFILE(SMBsplretq);
3111 /****************************************************************************
3112 Reply to a printwrite.
3113 ****************************************************************************/
3115 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3118 int outsize = set_message(outbuf,0,0,True);
3120 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3122 START_PROFILE(SMBsplwr);
3124 if (!CAN_PRINT(conn)) {
3125 END_PROFILE(SMBsplwr);
3126 return ERROR_DOS(ERRDOS,ERRnoaccess);
3129 CHECK_FSP(fsp,conn);
3132 numtowrite = SVAL(smb_buf(inbuf),1);
3133 data = smb_buf(inbuf) + 3;
3135 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3136 END_PROFILE(SMBsplwr);
3137 return(UNIXERROR(ERRHRD,ERRdiskfull));
3140 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3142 END_PROFILE(SMBsplwr);
3146 /****************************************************************************
3147 The guts of the mkdir command, split out so it may be called by the NT SMB
3149 ****************************************************************************/
3151 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3153 BOOL bad_path = False;
3154 SMB_STRUCT_STAT sbuf;
3157 unix_convert(directory,conn,0,&bad_path,&sbuf);
3159 if( strchr_m(directory, ':')) {
3160 return NT_STATUS_NOT_A_DIRECTORY;
3163 if (ms_has_wild(directory)) {
3164 return NT_STATUS_OBJECT_NAME_INVALID;
3167 if (check_name(directory, conn))
3168 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3171 if(errno == ENOENT) {
3173 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3175 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3177 return map_nt_error_from_unix(errno);
3180 return NT_STATUS_OK;
3183 /****************************************************************************
3185 ****************************************************************************/
3187 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3192 START_PROFILE(SMBmkdir);
3194 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3195 if (!NT_STATUS_IS_OK(status)) {
3196 END_PROFILE(SMBmkdir);
3197 return ERROR_NT(status);
3200 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3202 status = mkdir_internal(conn, directory);
3203 if (!NT_STATUS_IS_OK(status)) {
3204 END_PROFILE(SMBmkdir);
3205 return ERROR_NT(status);
3208 outsize = set_message(outbuf,0,0,True);
3210 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3212 END_PROFILE(SMBmkdir);
3216 /****************************************************************************
3217 Static function used by reply_rmdir to delete an entire directory
3218 tree recursively. Return False on ok, True on fail.
3219 ****************************************************************************/
3221 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3223 const char *dname = NULL;
3225 void *dirptr = OpenDir(conn, directory, False);
3230 while((dname = ReadDirName(dirptr))) {
3234 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3237 /* Construct the full name. */
3238 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3244 pstrcpy(fullname, directory);
3245 pstrcat(fullname, "/");
3246 pstrcat(fullname, dname);
3248 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3253 if(st.st_mode & S_IFDIR) {
3254 if(recursive_rmdir(conn, fullname)!=0) {
3258 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3262 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3271 /****************************************************************************
3272 The internals of the rmdir code - called elsewhere.
3273 ****************************************************************************/
3275 BOOL rmdir_internals(connection_struct *conn, char *directory)
3279 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3280 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3282 * Check to see if the only thing in this directory are
3283 * vetoed files/directories. If so then delete them and
3284 * retry. If we fail to delete any of them (and we *don't*
3285 * do a recursive delete) then fail the rmdir.
3287 BOOL all_veto_files = True;
3289 void *dirptr = OpenDir(conn, directory, False);
3291 if(dirptr != NULL) {
3292 int dirpos = TellDir(dirptr);
3293 while ((dname = ReadDirName(dirptr))) {
3294 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3296 if(!IS_VETO_PATH(conn, dname)) {
3297 all_veto_files = False;
3302 if(all_veto_files) {
3303 SeekDir(dirptr,dirpos);
3304 while ((dname = ReadDirName(dirptr))) {
3308 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3311 /* Construct the full name. */
3312 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3317 pstrcpy(fullname, directory);
3318 pstrcat(fullname, "/");
3319 pstrcat(fullname, dname);
3321 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3323 if(st.st_mode & S_IFDIR) {
3324 if(lp_recursive_veto_delete(SNUM(conn))) {
3325 if(recursive_rmdir(conn, fullname) != 0)
3328 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3330 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3334 /* Retry the rmdir */
3335 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3345 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3350 /****************************************************************************
3352 ****************************************************************************/
3354 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3359 BOOL bad_path = False;
3360 SMB_STRUCT_STAT sbuf;
3362 START_PROFILE(SMBrmdir);
3364 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3365 if (!NT_STATUS_IS_OK(status)) {
3366 END_PROFILE(SMBrmdir);
3367 return ERROR_NT(status);
3370 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3372 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3374 if (check_name(directory,conn)) {
3375 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3376 ok = rmdir_internals(conn, directory);
3380 END_PROFILE(SMBrmdir);
3381 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3384 outsize = set_message(outbuf,0,0,True);
3386 DEBUG( 3, ( "rmdir %s\n", directory ) );
3388 END_PROFILE(SMBrmdir);
3392 /*******************************************************************
3393 Resolve wildcards in a filename rename.
3394 Note that name is in UNIX charset and thus potentially can be more
3395 than fstring buffer (255 bytes) especially in default UTF-8 case.
3396 Therefore, we use pstring inside and all calls should ensure that
3397 name2 is at least pstring-long (they do already)
3398 ********************************************************************/
3400 static BOOL resolve_wildcards(const char *name1, char *name2)
3402 pstring root1,root2;
3404 char *p,*p2, *pname1, *pname2;
3405 int available_space, actual_space;
3408 pname1 = strrchr_m(name1,'/');
3409 pname2 = strrchr_m(name2,'/');
3411 if (!pname1 || !pname2)
3414 pstrcpy(root1,pname1);
3415 pstrcpy(root2,pname2);
3416 p = strrchr_m(root1,'.');
3423 p = strrchr_m(root2,'.');
3437 } else if (*p2 == '*') {
3453 } else if (*p2 == '*') {
3463 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3466 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3467 if (actual_space >= available_space - 1) {
3468 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3469 actual_space - available_space));
3472 pstrcpy_base(pname2, root2, name2);
3478 /****************************************************************************
3479 Ensure open files have their names updates.
3480 ****************************************************************************/
3482 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3485 BOOL did_rename = False;
3487 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3488 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3489 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3490 fsp->fsp_name, newname ));
3491 string_set(&fsp->fsp_name, newname);
3496 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3497 (unsigned int)dev, (double)inode, newname ));
3500 /****************************************************************************
3501 Rename an open file - given an fsp.
3502 ****************************************************************************/
3504 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3506 SMB_STRUCT_STAT sbuf;
3507 BOOL bad_path = False;
3508 pstring newname_last_component;
3509 NTSTATUS error = NT_STATUS_OK;
3514 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3516 /* Quick check for "." and ".." */
3517 if (!bad_path && newname_last_component[0] == '.') {
3518 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3519 return NT_STATUS_ACCESS_DENIED;
3522 if (!rcdest && bad_path) {
3523 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3526 /* Ensure newname contains a '/' */
3527 if(strrchr_m(newname,'/') == 0) {
3530 pstrcpy(tmpstr, "./");
3531 pstrcat(tmpstr, newname);
3532 pstrcpy(newname, tmpstr);
3536 * Check for special case with case preserving and not
3537 * case sensitive. If the old last component differs from the original
3538 * last component only by case, then we should allow
3539 * the rename (user is trying to change the case of the
3543 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3544 strequal(newname, fsp->fsp_name)) {
3546 pstring newname_modified_last_component;
3549 * Get the last component of the modified name.
3550 * Note that we guarantee that newname contains a '/'
3553 p = strrchr_m(newname,'/');
3554 pstrcpy(newname_modified_last_component,p+1);
3556 if(strcsequal(newname_modified_last_component,
3557 newname_last_component) == False) {
3559 * Replace the modified last component with
3562 pstrcpy(p+1, newname_last_component);
3567 * If the src and dest names are identical - including case,
3568 * don't do the rename, just return success.
3571 if (strcsequal(fsp->fsp_name, newname)) {
3572 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3574 return NT_STATUS_OK;
3577 dest_exists = vfs_object_exist(conn,newname,NULL);
3579 if(!replace_if_exists && dest_exists) {
3580 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3581 fsp->fsp_name,newname));
3582 return NT_STATUS_OBJECT_NAME_COLLISION;
3585 error = can_rename(newname,conn,&sbuf);
3587 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3588 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3589 nt_errstr(error), fsp->fsp_name,newname));
3590 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3591 error = NT_STATUS_ACCESS_DENIED;
3595 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3596 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3597 fsp->fsp_name,newname));
3598 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3599 return NT_STATUS_OK;
3602 if (errno == ENOTDIR || errno == EISDIR)
3603 error = NT_STATUS_OBJECT_NAME_COLLISION;
3605 error = map_nt_error_from_unix(errno);
3607 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3608 nt_errstr(error), fsp->fsp_name,newname));
3613 /****************************************************************************
3614 The guts of the rename command, split out so it may be called by the NT SMB
3616 ****************************************************************************/
3618 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3622 pstring last_component_src;
3623 pstring last_component_dest;
3626 BOOL bad_path_src = False;
3627 BOOL bad_path_dest = False;
3629 NTSTATUS error = NT_STATUS_OK;
3632 SMB_STRUCT_STAT sbuf1, sbuf2;
3634 *directory = *mask = 0;
3639 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3640 if (!rc && bad_path_src) {
3641 if (ms_has_wild(last_component_src))
3642 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3643 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3646 /* Quick check for "." and ".." */
3647 if (last_component_src[0] == '.') {
3648 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3649 return NT_STATUS_OBJECT_NAME_INVALID;
3653 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3655 /* Quick check for "." and ".." */
3656 if (last_component_dest[0] == '.') {
3657 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3658 return NT_STATUS_OBJECT_NAME_INVALID;
3663 * Split the old name into directory and last component
3664 * strings. Note that unix_convert may have stripped off a
3665 * leading ./ from both name and newname if the rename is
3666 * at the root of the share. We need to make sure either both
3667 * name and newname contain a / character or neither of them do
3668 * as this is checked in resolve_wildcards().
3671 p = strrchr_m(name,'/');
3673 pstrcpy(directory,".");
3677 pstrcpy(directory,name);
3679 *p = '/'; /* Replace needed for exceptional test below. */
3683 * We should only check the mangled cache
3684 * here if unix_convert failed. This means
3685 * that the path in 'mask' doesn't exist
3686 * on the file system and so we need to look
3687 * for a possible mangle. This patch from
3688 * Tine Smukavec <valentin.smukavec@hermes.si>.
3691 if (!rc && mangle_is_mangled(mask))
3692 mangle_check_cache( mask );
3694 has_wild = ms_has_wild(mask);
3698 * No wildcards - just process the one file.
3700 BOOL is_short_name = mangle_is_8_3(name, True);
3702 /* Add a terminating '/' to the directory name. */
3703 pstrcat(directory,"/");
3704 pstrcat(directory,mask);
3706 /* Ensure newname contains a '/' also */
3707 if(strrchr_m(newname,'/') == 0) {
3710 pstrcpy(tmpstr, "./");
3711 pstrcat(tmpstr, newname);
3712 pstrcpy(newname, tmpstr);
3715 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3716 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3717 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3718 newname, last_component_dest, is_short_name));
3721 * Check for special case with case preserving and not
3722 * case sensitive, if directory and newname are identical,
3723 * and the old last component differs from the original
3724 * last component only by case, then we should allow
3725 * the rename (user is trying to change the case of the
3728 if((conn->case_sensitive == False) &&
3729 (((conn->case_preserve == True) &&
3730 (is_short_name == False)) ||
3731 ((conn->short_case_preserve == True) &&
3732 (is_short_name == True))) &&
3733 strcsequal(directory, newname)) {
3734 pstring modified_last_component;
3737 * Get the last component of the modified name.
3738 * Note that we guarantee that newname contains a '/'
3741 p = strrchr_m(newname,'/');
3742 pstrcpy(modified_last_component,p+1);
3744 if(strcsequal(modified_last_component,
3745 last_component_dest) == False) {
3747 * Replace the modified last component with
3750 pstrcpy(p+1, last_component_dest);
3754 resolve_wildcards(directory,newname);
3757 * The source object must exist.
3760 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3761 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3762 directory,newname));
3764 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3766 * Must return different errors depending on whether the parent
3767 * directory existed or not.
3770 p = strrchr_m(directory, '/');
3772 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3774 if (vfs_object_exist(conn, directory, NULL))
3775 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3776 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3778 error = map_nt_error_from_unix(errno);
3779 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3780 nt_errstr(error), directory,newname));
3785 if (!rcdest && bad_path_dest) {
3786 if (ms_has_wild(last_component_dest))
3787 return NT_STATUS_OBJECT_NAME_INVALID;
3788 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3791 error = can_rename(directory,conn,&sbuf1);
3793 if (!NT_STATUS_IS_OK(error)) {
3794 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3795 nt_errstr(error), directory,newname));
3800 * If the src and dest names are identical - including case,
3801 * don't do the rename, just return success.
3804 if (strcsequal(directory, newname)) {
3805 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3806 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3807 return NT_STATUS_OK;
3810 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3811 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3812 directory,newname));
3813 return NT_STATUS_OBJECT_NAME_COLLISION;
3816 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3817 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3818 directory,newname));
3819 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3820 return NT_STATUS_OK;
3823 if (errno == ENOTDIR || errno == EISDIR)
3824 error = NT_STATUS_OBJECT_NAME_COLLISION;
3826 error = map_nt_error_from_unix(errno);
3828 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3829 nt_errstr(error), directory,newname));
3834 * Wildcards - process each file that matches.
3836 void *dirptr = NULL;
3840 if (check_name(directory,conn))
3841 dirptr = OpenDir(conn, directory, True);
3844 error = NT_STATUS_NO_SUCH_FILE;
3845 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3847 if (strequal(mask,"????????.???"))
3850 while ((dname = ReadDirName(dirptr))) {
3852 BOOL sysdir_entry = False;
3854 pstrcpy(fname,dname);
3856 /* Quick check for "." and ".." */
3857 if (fname[0] == '.') {
3858 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3860 sysdir_entry = True;
3867 if(!mask_match(fname, mask, conn->case_sensitive))
3871 error = NT_STATUS_OBJECT_NAME_INVALID;
3875 error = NT_STATUS_ACCESS_DENIED;
3876 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3877 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3878 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3879 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3882 error = can_rename(fname,conn,&sbuf1);
3883 if (!NT_STATUS_IS_OK(error)) {
3884 DEBUG(6,("rename %s refused\n", fname));
3887 pstrcpy(destname,newname);
3889 if (!resolve_wildcards(fname,destname)) {
3890 DEBUG(6,("resolve_wildcards %s %s failed\n",
3895 if (strcsequal(fname,destname)) {
3896 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3897 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3899 error = NT_STATUS_OK;
3903 if (!replace_if_exists &&
3904 vfs_file_exist(conn,destname, NULL)) {
3905 DEBUG(6,("file_exist %s\n", destname));
3906 error = NT_STATUS_OBJECT_NAME_COLLISION;
3910 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3911 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3913 error = NT_STATUS_OK;
3915 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3920 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3921 if (!rcdest && bad_path_dest) {
3922 if (ms_has_wild(last_component_dest))
3923 return NT_STATUS_OBJECT_NAME_INVALID;
3924 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3929 if (count == 0 && NT_STATUS_IS_OK(error)) {
3930 error = map_nt_error_from_unix(errno);
3936 /****************************************************************************
3938 ****************************************************************************/
3940 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3947 uint16 attrs = SVAL(inbuf,smb_vwv0);
3950 START_PROFILE(SMBmv);
3952 p = smb_buf(inbuf) + 1;
3953 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3954 if (!NT_STATUS_IS_OK(status)) {
3956 return ERROR_NT(status);
3959 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3960 if (!NT_STATUS_IS_OK(status)) {
3962 return ERROR_NT(status);
3965 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3966 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3968 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3970 status = rename_internals(conn, name, newname, attrs, False);
3971 if (!NT_STATUS_IS_OK(status)) {
3973 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
3974 /* We have re-scheduled this call. */
3975 clear_cached_errors();
3978 return ERROR_NT(status);
3982 * Win2k needs a changenotify request response before it will
3983 * update after a rename..
3985 process_pending_change_notify_queue((time_t)0);
3986 outsize = set_message(outbuf,0,0,True);
3992 /*******************************************************************
3993 Copy a file as part of a reply_copy.
3994 ******************************************************************/
3996 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3997 int count,BOOL target_is_directory, int *err_ret)
4000 SMB_STRUCT_STAT src_sbuf, sbuf2;
4002 files_struct *fsp1,*fsp2;
4008 pstrcpy(dest,dest1);
4009 if (target_is_directory) {
4010 char *p = strrchr_m(src,'/');
4019 if (!vfs_file_exist(conn,src,&src_sbuf))
4022 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4023 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4029 if (!target_is_directory && count)
4030 ofun = FILE_EXISTS_OPEN;
4032 dosattrs = dos_mode(conn, src, &src_sbuf);
4033 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4034 ZERO_STRUCTP(&sbuf2);
4036 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4037 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4040 close_file(fsp1,False);
4044 if ((ofun&3) == 1) {
4045 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4046 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4048 * Stop the copy from occurring.
4051 src_sbuf.st_size = 0;
4055 if (src_sbuf.st_size)
4056 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4058 close_file(fsp1,False);
4060 /* Ensure the modtime is set correctly on the destination file. */
4061 fsp2->pending_modtime = src_sbuf.st_mtime;
4064 * As we are opening fsp1 read-only we only expect
4065 * an error on close on fsp2 if we are out of space.
4066 * Thus we don't look at the error return from the
4069 *err_ret = close_file(fsp2,False);
4071 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4074 /****************************************************************************
4075 Reply to a file copy.
4076 ****************************************************************************/
4078 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4083 pstring mask,newname;
4086 int error = ERRnoaccess;
4090 int tid2 = SVAL(inbuf,smb_vwv0);
4091 int ofun = SVAL(inbuf,smb_vwv1);
4092 int flags = SVAL(inbuf,smb_vwv2);
4093 BOOL target_is_directory=False;
4094 BOOL bad_path1 = False;
4095 BOOL bad_path2 = False;
4097 SMB_STRUCT_STAT sbuf1, sbuf2;
4100 START_PROFILE(SMBcopy);
4102 *directory = *mask = 0;
4105 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4106 if (!NT_STATUS_IS_OK(status)) {
4107 END_PROFILE(SMBcopy);
4108 return ERROR_NT(status);
4110 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4111 if (!NT_STATUS_IS_OK(status)) {
4112 END_PROFILE(SMBcopy);
4113 return ERROR_NT(status);
4116 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4118 if (tid2 != conn->cnum) {
4119 /* can't currently handle inter share copies XXXX */
4120 DEBUG(3,("Rejecting inter-share copy\n"));
4121 END_PROFILE(SMBcopy);
4122 return ERROR_DOS(ERRSRV,ERRinvdevice);
4125 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4126 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4128 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4129 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4131 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4133 if ((flags&1) && target_is_directory) {
4134 END_PROFILE(SMBcopy);
4135 return ERROR_DOS(ERRDOS,ERRbadfile);
4138 if ((flags&2) && !target_is_directory) {
4139 END_PROFILE(SMBcopy);
4140 return ERROR_DOS(ERRDOS,ERRbadpath);
4143 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4144 /* wants a tree copy! XXXX */
4145 DEBUG(3,("Rejecting tree copy\n"));
4146 END_PROFILE(SMBcopy);
4147 return ERROR_DOS(ERRSRV,ERRerror);
4150 p = strrchr_m(name,'/');
4152 pstrcpy(directory,"./");
4156 pstrcpy(directory,name);
4161 * We should only check the mangled cache
4162 * here if unix_convert failed. This means
4163 * that the path in 'mask' doesn't exist
4164 * on the file system and so we need to look
4165 * for a possible mangle. This patch from
4166 * Tine Smukavec <valentin.smukavec@hermes.si>.
4169 if (!rc && mangle_is_mangled(mask))
4170 mangle_check_cache( mask );
4172 has_wild = ms_has_wild(mask);
4175 pstrcat(directory,"/");
4176 pstrcat(directory,mask);
4177 if (resolve_wildcards(directory,newname) &&
4178 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4182 END_PROFILE(SMBcopy);
4183 return(UNIXERROR(ERRHRD,ERRgeneral));
4186 exists = vfs_file_exist(conn,directory,NULL);
4189 void *dirptr = NULL;
4193 if (check_name(directory,conn))
4194 dirptr = OpenDir(conn, directory, True);
4199 if (strequal(mask,"????????.???"))
4202 while ((dname = ReadDirName(dirptr))) {
4204 pstrcpy(fname,dname);
4206 if(!mask_match(fname, mask, conn->case_sensitive))
4209 error = ERRnoaccess;
4210 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4211 pstrcpy(destname,newname);
4212 if (resolve_wildcards(fname,destname) &&
4213 copy_file(fname,destname,conn,ofun,
4214 count,target_is_directory,&err))
4216 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4224 /* Error on close... */
4226 END_PROFILE(SMBcopy);
4227 return(UNIXERROR(ERRHRD,ERRgeneral));
4231 END_PROFILE(SMBcopy);
4232 return ERROR_DOS(ERRDOS,error);
4234 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4235 unix_ERR_class = ERRDOS;
4236 unix_ERR_code = ERRbadpath;
4238 END_PROFILE(SMBcopy);
4239 return(UNIXERROR(ERRDOS,error));
4243 outsize = set_message(outbuf,1,0,True);
4244 SSVAL(outbuf,smb_vwv0,count);
4246 END_PROFILE(SMBcopy);
4250 /****************************************************************************
4252 ****************************************************************************/
4254 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4262 START_PROFILE(pathworks_setdir);
4265 if (!CAN_SETDIR(snum)) {
4266 END_PROFILE(pathworks_setdir);
4267 return ERROR_DOS(ERRDOS,ERRnoaccess);
4270 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4271 if (!NT_STATUS_IS_OK(status)) {
4272 END_PROFILE(pathworks_setdir);
4273 return ERROR_NT(status);
4276 if (strlen(newdir) == 0) {
4279 ok = vfs_directory_exist(conn,newdir,NULL);
4281 string_set(&conn->connectpath,newdir);
4285 END_PROFILE(pathworks_setdir);
4286 return ERROR_DOS(ERRDOS,ERRbadpath);
4289 outsize = set_message(outbuf,0,0,True);
4290 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4292 DEBUG(3,("setdir %s\n", newdir));
4294 END_PROFILE(pathworks_setdir);
4298 /****************************************************************************
4299 Get a lock pid, dealing with large count requests.
4300 ****************************************************************************/
4302 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4304 if(!large_file_format)
4305 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4307 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4310 /****************************************************************************
4311 Get a lock count, dealing with large count requests.
4312 ****************************************************************************/
4314 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4316 SMB_BIG_UINT count = 0;
4318 if(!large_file_format) {
4319 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4322 #if defined(HAVE_LONGLONG)
4323 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4324 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4325 #else /* HAVE_LONGLONG */
4328 * NT4.x seems to be broken in that it sends large file (64 bit)
4329 * lockingX calls even if the CAP_LARGE_FILES was *not*
4330 * negotiated. For boxes without large unsigned ints truncate the
4331 * lock count by dropping the top 32 bits.
4334 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4335 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4336 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4337 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4338 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4341 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4342 #endif /* HAVE_LONGLONG */
4348 #if !defined(HAVE_LONGLONG)
4349 /****************************************************************************
4350 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4351 ****************************************************************************/
4353 static uint32 map_lock_offset(uint32 high, uint32 low)
4357 uint32 highcopy = high;
4360 * Try and find out how many significant bits there are in high.
4363 for(i = 0; highcopy; i++)
4367 * We use 31 bits not 32 here as POSIX
4368 * lock offsets may not be negative.
4371 mask = (~0) << (31 - i);
4374 return 0; /* Fail. */
4380 #endif /* !defined(HAVE_LONGLONG) */
4382 /****************************************************************************
4383 Get a lock offset, dealing with large offset requests.
4384 ****************************************************************************/
4386 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4388 SMB_BIG_UINT offset = 0;
4392 if(!large_file_format) {
4393 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4396 #if defined(HAVE_LONGLONG)
4397 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4398 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4399 #else /* HAVE_LONGLONG */
4402 * NT4.x seems to be broken in that it sends large file (64 bit)
4403 * lockingX calls even if the CAP_LARGE_FILES was *not*
4404 * negotiated. For boxes without large unsigned ints mangle the
4405 * lock offset by mapping the top 32 bits onto the lower 32.
4408 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4409 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4410 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4413 if((new_low = map_lock_offset(high, low)) == 0) {
4415 return (SMB_BIG_UINT)-1;
4418 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4419 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4420 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4421 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4424 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4425 #endif /* HAVE_LONGLONG */
4431 /****************************************************************************
4432 Reply to a lockingX request.
4433 ****************************************************************************/
4435 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4437 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4438 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4439 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4440 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4441 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4442 SMB_BIG_UINT count = 0, offset = 0;
4444 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4447 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4449 BOOL my_lock_ctx = False;
4452 START_PROFILE(SMBlockingX);
4454 CHECK_FSP(fsp,conn);
4456 data = smb_buf(inbuf);
4458 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4459 /* we don't support these - and CANCEL_LOCK makes w2k
4460 and XP reboot so I don't really want to be
4461 compatible! (tridge) */
4462 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4465 /* Check if this is an oplock break on a file
4466 we have granted an oplock on.
4468 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4469 /* Client can insist on breaking to none. */
4470 BOOL break_to_none = (oplocklevel == 0);
4472 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4473 (unsigned int)oplocklevel, fsp->fnum ));
4476 * Make sure we have granted an exclusive or batch oplock on this file.
4479 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4480 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4481 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4483 /* if this is a pure oplock break request then don't send a reply */
4484 if (num_locks == 0 && num_ulocks == 0) {
4485 END_PROFILE(SMBlockingX);
4488 END_PROFILE(SMBlockingX);
4489 return ERROR_DOS(ERRDOS,ERRlock);
4493 if (remove_oplock(fsp, break_to_none) == False) {
4494 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4498 /* if this is a pure oplock break request then don't send a reply */
4499 if (num_locks == 0 && num_ulocks == 0) {
4500 /* Sanity check - ensure a pure oplock break is not a
4502 if(CVAL(inbuf,smb_vwv0) != 0xff)
4503 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4504 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4505 END_PROFILE(SMBlockingX);
4511 * We do this check *after* we have checked this is not a oplock break
4512 * response message. JRA.
4515 release_level_2_oplocks_on_change(fsp);
4517 /* Data now points at the beginning of the list
4518 of smb_unlkrng structs */
4519 for(i = 0; i < (int)num_ulocks; i++) {
4520 lock_pid = get_lock_pid( data, i, large_file_format);
4521 count = get_lock_count( data, i, large_file_format);
4522 offset = get_lock_offset( data, i, large_file_format, &err);
4525 * There is no error code marked "stupid client bug".... :-).
4528 END_PROFILE(SMBlockingX);
4529 return ERROR_DOS(ERRDOS,ERRnoaccess);
4532 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4533 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4535 status = do_unlock(fsp,conn,lock_pid,count,offset);
4536 if (NT_STATUS_V(status)) {
4537 END_PROFILE(SMBlockingX);
4538 return ERROR_NT(status);
4542 /* Setup the timeout in seconds. */
4544 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4546 /* Now do any requested locks */
4547 data += ((large_file_format ? 20 : 10)*num_ulocks);
4549 /* Data now points at the beginning of the list
4550 of smb_lkrng structs */
4552 for(i = 0; i < (int)num_locks; 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 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4566 (double)offset, (double)count, (unsigned int)lock_pid,
4567 fsp->fsp_name, (int)lock_timeout ));
4569 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4570 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4571 if (NT_STATUS_V(status)) {
4573 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4574 * Even if it's our own lock context, we need to wait here as
4575 * there may be an unlock on the way.
4576 * So I removed a "&& !my_lock_ctx" from the following
4577 * if statement. JRA.
4579 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4581 * A blocking lock was requested. Package up
4582 * this smb into a queued request and push it
4583 * onto the blocking lock queue.
4585 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4586 END_PROFILE(SMBlockingX);
4594 /* If any of the above locks failed, then we must unlock
4595 all of the previous locks (X/Open spec). */
4596 if (i != num_locks && num_locks != 0) {
4598 * Ensure we don't do a remove on the lock that just failed,
4599 * as under POSIX rules, if we have a lock already there, we
4600 * will delete it (and we shouldn't) .....
4602 for(i--; i >= 0; i--) {
4603 lock_pid = get_lock_pid( data, i, large_file_format);
4604 count = get_lock_count( data, i, large_file_format);
4605 offset = get_lock_offset( data, i, large_file_format, &err);
4608 * There is no error code marked "stupid client bug".... :-).
4611 END_PROFILE(SMBlockingX);
4612 return ERROR_DOS(ERRDOS,ERRnoaccess);
4615 do_unlock(fsp,conn,lock_pid,count,offset);
4617 END_PROFILE(SMBlockingX);
4618 return ERROR_NT(status);
4621 set_message(outbuf,2,0,True);
4623 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4624 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4626 END_PROFILE(SMBlockingX);
4627 return chain_reply(inbuf,outbuf,length,bufsize);
4630 /****************************************************************************
4631 Reply to a SMBreadbmpx (read block multiplex) request.
4632 ****************************************************************************/
4634 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4645 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4646 START_PROFILE(SMBreadBmpx);
4648 /* this function doesn't seem to work - disable by default */
4649 if (!lp_readbmpx()) {
4650 END_PROFILE(SMBreadBmpx);
4651 return ERROR_DOS(ERRSRV,ERRuseSTD);
4654 outsize = set_message(outbuf,8,0,True);
4656 CHECK_FSP(fsp,conn);
4659 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4660 maxcount = SVAL(inbuf,smb_vwv3);
4662 data = smb_buf(outbuf);
4663 pad = ((long)data)%4;
4668 max_per_packet = bufsize-(outsize+pad);
4672 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4673 END_PROFILE(SMBreadBmpx);
4674 return ERROR_DOS(ERRDOS,ERRlock);
4678 size_t N = MIN(max_per_packet,tcount-total_read);
4680 nread = read_file(fsp,data,startpos,N);
4685 if (nread < (ssize_t)N)
4686 tcount = total_read + nread;
4688 set_message(outbuf,8,nread,False);
4689 SIVAL(outbuf,smb_vwv0,startpos);
4690 SSVAL(outbuf,smb_vwv2,tcount);
4691 SSVAL(outbuf,smb_vwv6,nread);
4692 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4694 if (!send_smb(smbd_server_fd(),outbuf))
4695 exit_server("reply_readbmpx: send_smb failed.");
4697 total_read += nread;
4699 } while (total_read < (ssize_t)tcount);
4701 END_PROFILE(SMBreadBmpx);
4705 /****************************************************************************
4706 Reply to a SMBsetattrE.
4707 ****************************************************************************/
4709 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4711 struct utimbuf unix_times;
4713 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4714 START_PROFILE(SMBsetattrE);
4716 outsize = set_message(outbuf,0,0,True);
4718 if(!fsp || (fsp->conn != conn)) {
4719 END_PROFILE(SMBgetattrE);
4720 return ERROR_DOS(ERRDOS,ERRbadfid);
4724 * Convert the DOS times into unix times. Ignore create
4725 * time as UNIX can't set this.
4728 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4729 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4732 * Patch from Ray Frush <frush@engr.colostate.edu>
4733 * Sometimes times are sent as zero - ignore them.
4736 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4737 /* Ignore request */
4738 if( DEBUGLVL( 3 ) ) {
4739 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4740 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4742 END_PROFILE(SMBsetattrE);
4744 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4745 /* set modify time = to access time if modify time was 0 */
4746 unix_times.modtime = unix_times.actime;
4749 /* Set the date on this file */
4750 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4751 END_PROFILE(SMBsetattrE);
4752 return ERROR_DOS(ERRDOS,ERRnoaccess);
4755 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4756 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4758 END_PROFILE(SMBsetattrE);
4763 /* Back from the dead for OS/2..... JRA. */
4765 /****************************************************************************
4766 Reply to a SMBwritebmpx (write block multiplex primary) request.
4767 ****************************************************************************/
4769 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4772 ssize_t nwritten = -1;
4779 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4780 START_PROFILE(SMBwriteBmpx);
4782 CHECK_FSP(fsp,conn);
4786 tcount = SVAL(inbuf,smb_vwv1);
4787 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4788 write_through = BITSETW(inbuf+smb_vwv7,0);
4789 numtowrite = SVAL(inbuf,smb_vwv10);
4790 smb_doff = SVAL(inbuf,smb_vwv11);
4792 data = smb_base(inbuf) + smb_doff;
4794 /* If this fails we need to send an SMBwriteC response,
4795 not an SMBwritebmpx - set this up now so we don't forget */
4796 SCVAL(outbuf,smb_com,SMBwritec);
4798 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4799 END_PROFILE(SMBwriteBmpx);
4800 return(ERROR_DOS(ERRDOS,ERRlock));
4803 nwritten = write_file(fsp,data,startpos,numtowrite);
4805 if(lp_syncalways(SNUM(conn)) || write_through)
4806 sync_file(conn,fsp);
4808 if(nwritten < (ssize_t)numtowrite) {
4809 END_PROFILE(SMBwriteBmpx);
4810 return(UNIXERROR(ERRHRD,ERRdiskfull));
4813 /* If the maximum to be written to this file
4814 is greater than what we just wrote then set
4815 up a secondary struct to be attached to this
4816 fd, we will use this to cache error messages etc. */
4818 if((ssize_t)tcount > nwritten) {
4819 write_bmpx_struct *wbms;
4820 if(fsp->wbmpx_ptr != NULL)
4821 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4823 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4825 DEBUG(0,("Out of memory in reply_readmpx\n"));
4826 END_PROFILE(SMBwriteBmpx);
4827 return(ERROR_DOS(ERRSRV,ERRnoresource));
4829 wbms->wr_mode = write_through;
4830 wbms->wr_discard = False; /* No errors yet */
4831 wbms->wr_total_written = nwritten;
4832 wbms->wr_errclass = 0;
4834 fsp->wbmpx_ptr = wbms;
4837 /* We are returning successfully, set the message type back to
4839 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4841 outsize = set_message(outbuf,1,0,True);
4843 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4845 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4846 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4848 if (write_through && tcount==nwritten) {
4849 /* We need to send both a primary and a secondary response */
4850 smb_setlen(outbuf,outsize - 4);
4851 if (!send_smb(smbd_server_fd(),outbuf))
4852 exit_server("reply_writebmpx: send_smb failed.");
4854 /* Now the secondary */
4855 outsize = set_message(outbuf,1,0,True);
4856 SCVAL(outbuf,smb_com,SMBwritec);
4857 SSVAL(outbuf,smb_vwv0,nwritten);
4860 END_PROFILE(SMBwriteBmpx);
4864 /****************************************************************************
4865 Reply to a SMBwritebs (write block multiplex secondary) request.
4866 ****************************************************************************/
4868 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4871 ssize_t nwritten = -1;
4878 write_bmpx_struct *wbms;
4879 BOOL send_response = False;
4880 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4881 START_PROFILE(SMBwriteBs);
4883 CHECK_FSP(fsp,conn);
4886 tcount = SVAL(inbuf,smb_vwv1);
4887 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4888 numtowrite = SVAL(inbuf,smb_vwv6);
4889 smb_doff = SVAL(inbuf,smb_vwv7);
4891 data = smb_base(inbuf) + smb_doff;
4893 /* We need to send an SMBwriteC response, not an SMBwritebs */
4894 SCVAL(outbuf,smb_com,SMBwritec);
4896 /* This fd should have an auxiliary struct attached,
4897 check that it does */
4898 wbms = fsp->wbmpx_ptr;
4900 END_PROFILE(SMBwriteBs);
4904 /* If write through is set we can return errors, else we must cache them */
4905 write_through = wbms->wr_mode;
4907 /* Check for an earlier error */
4908 if(wbms->wr_discard) {
4909 END_PROFILE(SMBwriteBs);
4910 return -1; /* Just discard the packet */
4913 nwritten = write_file(fsp,data,startpos,numtowrite);
4915 if(lp_syncalways(SNUM(conn)) || write_through)
4916 sync_file(conn,fsp);
4918 if (nwritten < (ssize_t)numtowrite) {
4920 /* We are returning an error - we can delete the aux struct */
4923 fsp->wbmpx_ptr = NULL;
4924 END_PROFILE(SMBwriteBs);
4925 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4927 END_PROFILE(SMBwriteBs);
4928 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4931 /* Increment the total written, if this matches tcount
4932 we can discard the auxiliary struct (hurrah !) and return a writeC */
4933 wbms->wr_total_written += nwritten;
4934 if(wbms->wr_total_written >= tcount) {
4935 if (write_through) {
4936 outsize = set_message(outbuf,1,0,True);
4937 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4938 send_response = True;
4942 fsp->wbmpx_ptr = NULL;
4946 END_PROFILE(SMBwriteBs);
4950 END_PROFILE(SMBwriteBs);
4954 /****************************************************************************
4955 Reply to a SMBgetattrE.
4956 ****************************************************************************/
4958 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4960 SMB_STRUCT_STAT sbuf;
4963 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4964 START_PROFILE(SMBgetattrE);
4966 outsize = set_message(outbuf,11,0,True);
4968 if(!fsp || (fsp->conn != conn)) {
4969 END_PROFILE(SMBgetattrE);
4970 return ERROR_DOS(ERRDOS,ERRbadfid);
4973 /* Do an fstat on this file */
4974 if(fsp_stat(fsp, &sbuf)) {
4975 END_PROFILE(SMBgetattrE);
4976 return(UNIXERROR(ERRDOS,ERRnoaccess));
4979 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4982 * Convert the times into dos times. Set create
4983 * date to be last modify date as UNIX doesn't save
4987 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4988 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4989 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4992 SIVAL(outbuf,smb_vwv6,0);
4993 SIVAL(outbuf,smb_vwv8,0);
4995 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4996 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4997 SIVAL(outbuf,smb_vwv8,allocation_size);
4999 SSVAL(outbuf,smb_vwv10, mode);
5001 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5003 END_PROFILE(SMBgetattrE);