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);
492 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
497 END_PROFILE(SMBioctl);
501 /****************************************************************************
503 ****************************************************************************/
505 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
511 BOOL bad_path = False;
512 SMB_STRUCT_STAT sbuf;
515 START_PROFILE(SMBchkpth);
517 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
518 if (!NT_STATUS_IS_OK(status)) {
519 END_PROFILE(SMBchkpth);
520 return ERROR_NT(status);
523 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
525 unix_convert(name,conn,0,&bad_path,&sbuf);
527 mode = SVAL(inbuf,smb_vwv0);
529 if (check_name(name,conn)) {
530 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
531 if (!(ok = S_ISDIR(sbuf.st_mode))) {
532 END_PROFILE(SMBchkpth);
533 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
538 /* We special case this - as when a Windows machine
539 is parsing a path is steps through the components
540 one at a time - if a component fails it expects
541 ERRbadpath, not ERRbadfile.
543 if(errno == ENOENT) {
545 * Windows returns different error codes if
546 * the parent directory is valid but not the
547 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
548 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
549 * if the path is invalid.
552 END_PROFILE(SMBchkpth);
553 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
555 END_PROFILE(SMBchkpth);
556 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
558 } else if (errno == ENOTDIR) {
559 END_PROFILE(SMBchkpth);
560 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
563 END_PROFILE(SMBchkpth);
564 return(UNIXERROR(ERRDOS,ERRbadpath));
567 outsize = set_message(outbuf,0,0,True);
569 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
571 END_PROFILE(SMBchkpth);
575 /****************************************************************************
577 ****************************************************************************/
579 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
583 SMB_STRUCT_STAT sbuf;
588 BOOL bad_path = False;
592 START_PROFILE(SMBgetatr);
594 p = smb_buf(inbuf) + 1;
595 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
596 if (!NT_STATUS_IS_OK(status)) {
597 END_PROFILE(SMBgetatr);
598 return ERROR_NT(status);
601 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
603 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
604 under WfWg - weird! */
606 mode = aHIDDEN | aDIR;
607 if (!CAN_WRITE(conn))
613 unix_convert(fname,conn,0,&bad_path,&sbuf);
614 if (check_name(fname,conn)) {
615 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
616 mode = dos_mode(conn,fname,&sbuf);
618 mtime = sbuf.st_mtime;
623 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
629 END_PROFILE(SMBgetatr);
630 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
633 outsize = set_message(outbuf,10,0,True);
635 SSVAL(outbuf,smb_vwv0,mode);
636 if(lp_dos_filetime_resolution(SNUM(conn)) )
637 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
639 put_dos_date3(outbuf,smb_vwv1,mtime);
640 SIVAL(outbuf,smb_vwv3,(uint32)size);
642 if (Protocol >= PROTOCOL_NT1)
643 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
645 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
647 END_PROFILE(SMBgetatr);
651 /****************************************************************************
653 ****************************************************************************/
655 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
662 SMB_STRUCT_STAT sbuf;
663 BOOL bad_path = False;
667 START_PROFILE(SMBsetatr);
669 p = smb_buf(inbuf) + 1;
670 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
671 if (!NT_STATUS_IS_OK(status)) {
672 END_PROFILE(SMBsetatr);
673 return ERROR_NT(status);
676 unix_convert(fname,conn,0,&bad_path,&sbuf);
678 mode = SVAL(inbuf,smb_vwv0);
679 mtime = make_unix_date3(inbuf+smb_vwv1);
681 if (mode != FILE_ATTRIBUTE_NORMAL) {
682 if (VALID_STAT_OF_DIR(sbuf))
687 if (check_name(fname,conn)) {
688 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
695 ok = set_filetime(conn,fname,mtime);
698 END_PROFILE(SMBsetatr);
699 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
702 outsize = set_message(outbuf,0,0,True);
704 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
706 END_PROFILE(SMBsetatr);
710 /****************************************************************************
712 ****************************************************************************/
714 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
717 SMB_BIG_UINT dfree,dsize,bsize;
718 START_PROFILE(SMBdskattr);
720 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
722 outsize = set_message(outbuf,5,0,True);
724 if (Protocol <= PROTOCOL_LANMAN2) {
725 double total_space, free_space;
726 /* we need to scale this to a number that DOS6 can handle. We
727 use floating point so we can handle large drives on systems
728 that don't have 64 bit integers
730 we end up displaying a maximum of 2G to DOS systems
732 total_space = dsize * (double)bsize;
733 free_space = dfree * (double)bsize;
735 dsize = (total_space+63*512) / (64*512);
736 dfree = (free_space+63*512) / (64*512);
738 if (dsize > 0xFFFF) dsize = 0xFFFF;
739 if (dfree > 0xFFFF) dfree = 0xFFFF;
741 SSVAL(outbuf,smb_vwv0,dsize);
742 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
743 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
744 SSVAL(outbuf,smb_vwv3,dfree);
746 SSVAL(outbuf,smb_vwv0,dsize);
747 SSVAL(outbuf,smb_vwv1,bsize/512);
748 SSVAL(outbuf,smb_vwv2,512);
749 SSVAL(outbuf,smb_vwv3,dfree);
752 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
754 END_PROFILE(SMBdskattr);
758 /****************************************************************************
760 Can be called from SMBsearch, SMBffirst or SMBfunique.
761 ****************************************************************************/
763 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
773 unsigned int numentries = 0;
774 unsigned int maxentries = 0;
775 BOOL finished = False;
782 BOOL check_descend = False;
783 BOOL expect_close = False;
784 BOOL can_open = True;
785 BOOL bad_path = False;
787 START_PROFILE(SMBsearch);
789 *mask = *directory = *fname = 0;
791 /* If we were called as SMBffirst then we must expect close. */
792 if(CVAL(inbuf,smb_com) == SMBffirst)
795 outsize = set_message(outbuf,1,3,True);
796 maxentries = SVAL(inbuf,smb_vwv0);
797 dirtype = SVAL(inbuf,smb_vwv1);
798 p = smb_buf(inbuf) + 1;
799 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
800 if (!NT_STATUS_IS_OK(nt_status)) {
801 END_PROFILE(SMBsearch);
802 return ERROR_NT(nt_status);
805 status_len = SVAL(p, 0);
808 /* dirtype &= ~aDIR; */
810 if (status_len == 0) {
811 SMB_STRUCT_STAT sbuf;
814 pstrcpy(directory,path);
816 unix_convert(directory,conn,0,&bad_path,&sbuf);
819 if (!check_name(directory,conn))
822 p = strrchr_m(dir2,'/');
831 p = strrchr_m(directory,'/');
837 if (strlen(directory) == 0)
838 pstrcpy(directory,".");
839 memset((char *)status,'\0',21);
840 SCVAL(status,0,(dirtype & 0x1F));
845 status_dirtype = CVAL(status,0) & 0x1F;
846 if (status_dirtype != (dirtype & 0x1F))
847 dirtype = status_dirtype;
849 conn->dirptr = dptr_fetch(status+12,&dptr_num);
852 string_set(&conn->dirpath,dptr_path(dptr_num));
853 pstrcpy(mask, dptr_wcard(dptr_num));
857 p = smb_buf(outbuf) + 3;
860 if (status_len == 0) {
861 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
864 END_PROFILE(SMBsearch);
865 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
867 END_PROFILE(SMBsearch);
868 return ERROR_DOS(ERRDOS,ERRnofids);
870 dptr_set_wcard(dptr_num, strdup(mask));
871 dptr_set_attr(dptr_num, dirtype);
873 dirtype = dptr_attr(dptr_num);
876 DEBUG(4,("dptr_num is %d\n",dptr_num));
879 if ((dirtype&0x1F) == aVOLID) {
881 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
882 dptr_fill(p+12,dptr_num);
883 if (dptr_zero(p+12) && (status_len==0))
887 p += DIR_STRUCT_SIZE;
890 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
892 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
893 conn->dirpath,lp_dontdescend(SNUM(conn))));
894 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
895 check_descend = True;
897 for (i=numentries;(i<maxentries) && !finished;i++) {
898 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
901 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
902 dptr_fill(p+12,dptr_num);
905 p += DIR_STRUCT_SIZE;
914 /* If we were called as SMBffirst with smb_search_id == NULL
915 and no entries were found then return error and close dirptr
918 if(ok && expect_close && numentries == 0 && status_len == 0) {
919 if (Protocol < PROTOCOL_NT1) {
920 SCVAL(outbuf,smb_rcls,ERRDOS);
921 SSVAL(outbuf,smb_err,ERRnofiles);
923 /* Also close the dptr - we know it's gone */
924 dptr_close(&dptr_num);
925 } else if (numentries == 0 || !ok) {
926 if (Protocol < PROTOCOL_NT1) {
927 SCVAL(outbuf,smb_rcls,ERRDOS);
928 SSVAL(outbuf,smb_err,ERRnofiles);
930 dptr_close(&dptr_num);
933 /* If we were called as SMBfunique, then we can close the dirptr now ! */
934 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
935 dptr_close(&dptr_num);
937 SSVAL(outbuf,smb_vwv0,numentries);
938 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
939 SCVAL(smb_buf(outbuf),0,5);
940 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
942 if (Protocol >= PROTOCOL_NT1)
943 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
945 outsize += DIR_STRUCT_SIZE*numentries;
946 smb_setlen(outbuf,outsize - 4);
948 if ((! *directory) && dptr_path(dptr_num))
949 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
951 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
952 smb_fn_name(CVAL(inbuf,smb_com)),
953 mask, directory, dirtype, numentries, maxentries ) );
955 END_PROFILE(SMBsearch);
959 /****************************************************************************
960 Reply to a fclose (stop directory search).
961 ****************************************************************************/
963 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
973 START_PROFILE(SMBfclose);
975 outsize = set_message(outbuf,1,0,True);
976 p = smb_buf(inbuf) + 1;
977 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
978 if (!NT_STATUS_IS_OK(err)) {
979 END_PROFILE(SMBfclose);
980 return ERROR_NT(err);
983 status_len = SVAL(p,0);
986 if (status_len == 0) {
987 END_PROFILE(SMBfclose);
988 return ERROR_DOS(ERRSRV,ERRsrverror);
993 if(dptr_fetch(status+12,&dptr_num)) {
994 /* Close the dptr - we know it's gone */
995 dptr_close(&dptr_num);
998 SSVAL(outbuf,smb_vwv0,0);
1000 DEBUG(3,("search close\n"));
1002 END_PROFILE(SMBfclose);
1006 /****************************************************************************
1008 ****************************************************************************/
1010 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1019 SMB_STRUCT_STAT sbuf;
1020 BOOL bad_path = False;
1022 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1023 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1025 START_PROFILE(SMBopen);
1027 share_mode = SVAL(inbuf,smb_vwv0);
1029 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1030 if (!NT_STATUS_IS_OK(status)) {
1031 END_PROFILE(SMBopen);
1032 return ERROR_NT(status);
1035 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1037 unix_convert(fname,conn,0,&bad_path,&sbuf);
1039 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1040 (uint32)dos_attr, oplock_request,&rmode,NULL);
1043 END_PROFILE(SMBopen);
1044 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1047 size = sbuf.st_size;
1048 fmode = dos_mode(conn,fname,&sbuf);
1049 mtime = sbuf.st_mtime;
1052 DEBUG(3,("attempt to open a directory %s\n",fname));
1053 close_file(fsp,False);
1054 END_PROFILE(SMBopen);
1055 return ERROR_DOS(ERRDOS,ERRnoaccess);
1058 outsize = set_message(outbuf,7,0,True);
1059 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1060 SSVAL(outbuf,smb_vwv1,fmode);
1061 if(lp_dos_filetime_resolution(SNUM(conn)) )
1062 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1064 put_dos_date3(outbuf,smb_vwv2,mtime);
1065 SIVAL(outbuf,smb_vwv4,(uint32)size);
1066 SSVAL(outbuf,smb_vwv6,rmode);
1068 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1069 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1071 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1072 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1073 END_PROFILE(SMBopen);
1077 /****************************************************************************
1078 Reply to an open and X.
1079 ****************************************************************************/
1081 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1084 int smb_mode = SVAL(inbuf,smb_vwv3);
1085 int smb_attr = SVAL(inbuf,smb_vwv5);
1086 /* Breakout the oplock request bits so we can set the
1087 reply bits separately. */
1088 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1089 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1090 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1092 int open_flags = SVAL(inbuf,smb_vwv2);
1093 int smb_sattr = SVAL(inbuf,smb_vwv4);
1094 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1096 int smb_ofun = SVAL(inbuf,smb_vwv8);
1098 int fmode=0,mtime=0,rmode=0;
1099 SMB_STRUCT_STAT sbuf;
1101 BOOL bad_path = False;
1104 START_PROFILE(SMBopenX);
1106 /* If it's an IPC, pass off the pipe handler. */
1108 if (lp_nt_pipe_support()) {
1109 END_PROFILE(SMBopenX);
1110 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1112 END_PROFILE(SMBopenX);
1113 return ERROR_DOS(ERRSRV,ERRaccess);
1117 /* XXXX we need to handle passed times, sattr and flags */
1118 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 END_PROFILE(SMBopenX);
1121 return ERROR_NT(status);
1124 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1126 unix_convert(fname,conn,0,&bad_path,&sbuf);
1128 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1129 oplock_request, &rmode,&smb_action);
1132 END_PROFILE(SMBopenX);
1133 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1136 size = sbuf.st_size;
1137 fmode = dos_mode(conn,fname,&sbuf);
1138 mtime = sbuf.st_mtime;
1140 close_file(fsp,False);
1141 END_PROFILE(SMBopenX);
1142 return ERROR_DOS(ERRDOS,ERRnoaccess);
1145 /* If the caller set the extended oplock request bit
1146 and we granted one (by whatever means) - set the
1147 correct bit for extended oplock reply.
1150 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1151 smb_action |= EXTENDED_OPLOCK_GRANTED;
1153 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1154 smb_action |= EXTENDED_OPLOCK_GRANTED;
1156 /* If the caller set the core oplock request bit
1157 and we granted one (by whatever means) - set the
1158 correct bit for core oplock reply.
1161 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1162 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1164 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1165 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1167 set_message(outbuf,15,0,True);
1168 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1169 SSVAL(outbuf,smb_vwv3,fmode);
1170 if(lp_dos_filetime_resolution(SNUM(conn)) )
1171 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1173 put_dos_date3(outbuf,smb_vwv4,mtime);
1174 SIVAL(outbuf,smb_vwv6,(uint32)size);
1175 SSVAL(outbuf,smb_vwv8,rmode);
1176 SSVAL(outbuf,smb_vwv11,smb_action);
1178 END_PROFILE(SMBopenX);
1179 return chain_reply(inbuf,outbuf,length,bufsize);
1182 /****************************************************************************
1183 Reply to a SMBulogoffX.
1184 ****************************************************************************/
1186 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1188 uint16 vuid = SVAL(inbuf,smb_uid);
1189 user_struct *vuser = get_valid_user_struct(vuid);
1190 START_PROFILE(SMBulogoffX);
1193 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1195 /* in user level security we are supposed to close any files
1196 open by this user */
1197 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1198 file_close_user(vuid);
1200 invalidate_vuid(vuid);
1202 set_message(outbuf,2,0,True);
1204 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1206 END_PROFILE(SMBulogoffX);
1207 return chain_reply(inbuf,outbuf,length,bufsize);
1210 /****************************************************************************
1211 Reply to a mknew or a create.
1212 ****************************************************************************/
1214 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1221 BOOL bad_path = False;
1223 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1224 SMB_STRUCT_STAT sbuf;
1226 START_PROFILE(SMBcreate);
1228 com = SVAL(inbuf,smb_com);
1230 createmode = SVAL(inbuf,smb_vwv0);
1231 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1232 if (!NT_STATUS_IS_OK(status)) {
1233 END_PROFILE(SMBcreate);
1234 return ERROR_NT(status);
1237 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1239 unix_convert(fname,conn,0,&bad_path,&sbuf);
1241 if (createmode & aVOLID)
1242 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1244 if(com == SMBmknew) {
1245 /* We should fail if file exists. */
1246 ofun = FILE_CREATE_IF_NOT_EXIST;
1248 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1249 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1252 /* Open file in dos compatibility share mode. */
1253 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1254 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1257 END_PROFILE(SMBcreate);
1258 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1261 outsize = set_message(outbuf,1,0,True);
1262 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1264 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1265 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1267 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1268 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1270 DEBUG( 2, ( "new file %s\n", fname ) );
1271 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1273 END_PROFILE(SMBcreate);
1277 /****************************************************************************
1278 Reply to a create temporary file.
1279 ****************************************************************************/
1281 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1286 BOOL bad_path = False;
1288 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1290 SMB_STRUCT_STAT sbuf;
1293 unsigned int namelen;
1295 START_PROFILE(SMBctemp);
1297 createattr = SVAL(inbuf,smb_vwv0);
1298 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1299 if (!NT_STATUS_IS_OK(status)) {
1300 END_PROFILE(SMBctemp);
1301 return ERROR_NT(status);
1304 pstrcat(fname,"/TMXXXXXX");
1306 pstrcat(fname,"TMXXXXXX");
1309 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1311 unix_convert(fname,conn,0,&bad_path,&sbuf);
1313 tmpfd = smb_mkstemp(fname);
1315 END_PROFILE(SMBctemp);
1316 return(UNIXERROR(ERRDOS,ERRnoaccess));
1319 SMB_VFS_STAT(conn,fname,&sbuf);
1321 /* Open file in dos compatibility share mode. */
1322 /* We should fail if file does not exist. */
1323 fsp = open_file_shared(conn,fname,&sbuf,
1324 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1325 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1326 (uint32)createattr, oplock_request, NULL, NULL);
1328 /* close fd from smb_mkstemp() */
1332 END_PROFILE(SMBctemp);
1333 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1336 outsize = set_message(outbuf,1,0,True);
1337 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1339 /* the returned filename is relative to the directory */
1340 s = strrchr_m(fname, '/');
1346 p = smb_buf(outbuf);
1348 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1349 thing in the byte section. JRA */
1350 SSVALS(p, 0, -1); /* what is this? not in spec */
1352 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1354 outsize = set_message_end(outbuf, p);
1356 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1357 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1359 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1360 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1362 DEBUG( 2, ( "created temp file %s\n", fname ) );
1363 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1364 fname, fsp->fd, sbuf.st_mode ) );
1366 END_PROFILE(SMBctemp);
1370 /*******************************************************************
1371 Check if a user is allowed to rename a file.
1372 ********************************************************************/
1374 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1380 if (!CAN_WRITE(conn))
1381 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1383 if (S_ISDIR(pst->st_mode))
1384 return NT_STATUS_OK;
1386 /* We need a better way to return NT status codes from open... */
1390 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1391 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1394 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1395 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1396 ret = NT_STATUS_SHARING_VIOLATION;
1399 unix_ERR_ntstatus = NT_STATUS_OK;
1402 close_file(fsp,False);
1403 return NT_STATUS_OK;
1406 /*******************************************************************
1407 Check if a user is allowed to delete a file.
1408 ********************************************************************/
1410 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1412 SMB_STRUCT_STAT sbuf;
1418 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1421 if (!CAN_WRITE(conn))
1422 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1424 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1425 if(errno == ENOENT) {
1427 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1429 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1431 return map_nt_error_from_unix(errno);
1434 fmode = dos_mode(conn,fname,&sbuf);
1436 /* Can't delete a directory. */
1438 return NT_STATUS_FILE_IS_A_DIRECTORY;
1440 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1441 return NT_STATUS_OBJECT_NAME_INVALID;
1442 #endif /* JRATEST */
1444 if (!lp_delete_readonly(SNUM(conn))) {
1446 return NT_STATUS_CANNOT_DELETE;
1448 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1449 return NT_STATUS_NO_SUCH_FILE;
1451 /* We need a better way to return NT status codes from open... */
1455 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1456 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1459 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1460 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1461 ret = unix_ERR_ntstatus;
1462 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1463 ret = NT_STATUS_SHARING_VIOLATION;
1466 unix_ERR_ntstatus = NT_STATUS_OK;
1469 close_file(fsp,False);
1470 return NT_STATUS_OK;
1473 /****************************************************************************
1474 The guts of the unlink command, split out so it may be called by the NT SMB
1476 ****************************************************************************/
1478 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1484 NTSTATUS error = NT_STATUS_OK;
1486 BOOL bad_path = False;
1488 SMB_STRUCT_STAT sbuf;
1490 *directory = *mask = 0;
1492 /* We must check for wildcards in the name given
1493 * directly by the client - before any unmangling.
1494 * This prevents an unmangling of a UNIX name containing
1495 * a DOS wildcard like '*' or '?' from unmangling into
1496 * a wildcard delete which was not intended.
1497 * FIX for #226. JRA.
1500 has_wild = ms_has_wild(name);
1502 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1504 p = strrchr_m(name,'/');
1506 pstrcpy(directory,".");
1510 pstrcpy(directory,name);
1515 * We should only check the mangled cache
1516 * here if unix_convert failed. This means
1517 * that the path in 'mask' doesn't exist
1518 * on the file system and so we need to look
1519 * for a possible mangle. This patch from
1520 * Tine Smukavec <valentin.smukavec@hermes.si>.
1523 if (!rc && mangle_is_mangled(mask))
1524 mangle_check_cache( mask );
1527 pstrcat(directory,"/");
1528 pstrcat(directory,mask);
1529 error = can_delete(directory,conn,dirtype,bad_path);
1530 if (!NT_STATUS_IS_OK(error))
1533 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1537 void *dirptr = NULL;
1540 if (check_name(directory,conn))
1541 dirptr = OpenDir(conn, directory, True);
1543 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1544 the pattern matches against the long name, otherwise the short name
1545 We don't implement this yet XXXX
1549 error = NT_STATUS_NO_SUCH_FILE;
1551 if (strequal(mask,"????????.???"))
1554 while ((dname = ReadDirName(dirptr))) {
1556 BOOL sys_direntry = False;
1557 pstrcpy(fname,dname);
1559 /* Quick check for "." and ".." */
1560 if (fname[0] == '.') {
1561 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1562 if ((dirtype & aDIR)) {
1563 sys_direntry = True;
1570 if(!mask_match(fname, mask, conn->case_sensitive))
1574 error = NT_STATUS_OBJECT_NAME_INVALID;
1578 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1579 error = can_delete(fname,conn,dirtype,bad_path);
1580 if (!NT_STATUS_IS_OK(error)) {
1583 if (SMB_VFS_UNLINK(conn,fname) == 0)
1585 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1591 if (count == 0 && NT_STATUS_IS_OK(error)) {
1592 error = map_nt_error_from_unix(errno);
1598 /****************************************************************************
1600 ****************************************************************************/
1602 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1609 START_PROFILE(SMBunlink);
1611 dirtype = SVAL(inbuf,smb_vwv0);
1613 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 END_PROFILE(SMBunlink);
1616 return ERROR_NT(status);
1619 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1621 DEBUG(3,("reply_unlink : %s\n",name));
1623 status = unlink_internals(conn, dirtype, name);
1624 if (!NT_STATUS_IS_OK(status))
1625 return ERROR_NT(status);
1628 * Win2k needs a changenotify request response before it will
1629 * update after a rename..
1631 process_pending_change_notify_queue((time_t)0);
1633 outsize = set_message(outbuf,0,0,True);
1635 END_PROFILE(SMBunlink);
1639 /****************************************************************************
1641 ****************************************************************************/
1643 void fail_readraw(void)
1646 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1648 exit_server(errstr);
1651 /****************************************************************************
1652 Use sendfile in readbraw.
1653 ****************************************************************************/
1655 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1656 ssize_t mincount, char *outbuf)
1660 #if defined(WITH_SENDFILE)
1662 * We can only use sendfile on a non-chained packet and on a file
1663 * that is exclusively oplocked. reply_readbraw has already checked the length.
1666 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1667 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1670 _smb_setlen(outbuf,nread);
1671 header.data = outbuf;
1675 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1677 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1678 * return ENOSYS then pretend we just got a normal read.
1680 if (errno == ENOSYS)
1683 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1684 fsp->fsp_name, strerror(errno) ));
1685 exit_server("send_file_readbraw sendfile failed");
1694 ret = read_file(fsp,outbuf+4,startpos,nread);
1695 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1704 _smb_setlen(outbuf,ret);
1705 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1709 /****************************************************************************
1710 Reply to a readbraw (core+ protocol).
1711 ****************************************************************************/
1713 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1715 extern struct current_user current_user;
1716 ssize_t maxcount,mincount;
1719 char *header = outbuf;
1721 START_PROFILE(SMBreadbraw);
1723 if (srv_is_signing_active()) {
1724 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1728 * Special check if an oplock break has been issued
1729 * and the readraw request croses on the wire, we must
1730 * return a zero length response here.
1733 if(global_oplock_break) {
1734 _smb_setlen(header,0);
1735 if (write_data(smbd_server_fd(),header,4) != 4)
1737 DEBUG(5,("readbraw - oplock break finished\n"));
1738 END_PROFILE(SMBreadbraw);
1742 fsp = file_fsp(inbuf,smb_vwv0);
1744 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1746 * fsp could be NULL here so use the value from the packet. JRA.
1748 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1749 _smb_setlen(header,0);
1750 if (write_data(smbd_server_fd(),header,4) != 4)
1752 END_PROFILE(SMBreadbraw);
1756 CHECK_FSP(fsp,conn);
1758 flush_write_cache(fsp, READRAW_FLUSH);
1760 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1761 if(CVAL(inbuf,smb_wct) == 10) {
1763 * This is a large offset (64 bit) read.
1765 #ifdef LARGE_SMB_OFF_T
1767 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1769 #else /* !LARGE_SMB_OFF_T */
1772 * Ensure we haven't been sent a >32 bit offset.
1775 if(IVAL(inbuf,smb_vwv8) != 0) {
1776 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1777 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1778 _smb_setlen(header,0);
1779 if (write_data(smbd_server_fd(),header,4) != 4)
1781 END_PROFILE(SMBreadbraw);
1785 #endif /* LARGE_SMB_OFF_T */
1788 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1789 _smb_setlen(header,0);
1790 if (write_data(smbd_server_fd(),header,4) != 4)
1792 END_PROFILE(SMBreadbraw);
1796 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1797 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1799 /* ensure we don't overrun the packet size */
1800 maxcount = MIN(65535,maxcount);
1802 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1803 SMB_OFF_T size = fsp->size;
1804 SMB_OFF_T sizeneeded = startpos + maxcount;
1806 if (size < sizeneeded) {
1808 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1810 if (!fsp->can_write)
1814 if (startpos >= size)
1817 nread = MIN(maxcount,(size - startpos));
1820 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1821 if (nread < mincount)
1825 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1826 (int)maxcount, (int)mincount, (int)nread ) );
1828 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1830 DEBUG(5,("readbraw finished\n"));
1831 END_PROFILE(SMBreadbraw);
1835 /****************************************************************************
1836 Reply to a lockread (core+ protocol).
1837 ****************************************************************************/
1839 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1847 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1848 BOOL my_lock_ctx = False;
1849 START_PROFILE(SMBlockread);
1851 CHECK_FSP(fsp,conn);
1854 release_level_2_oplocks_on_change(fsp);
1856 numtoread = SVAL(inbuf,smb_vwv1);
1857 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1859 outsize = set_message(outbuf,5,3,True);
1860 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1861 data = smb_buf(outbuf) + 3;
1864 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1865 * protocol request that predates the read/write lock concept.
1866 * Thus instead of asking for a read lock here we need to ask
1867 * for a write lock. JRA.
1868 * Note that the requested lock size is unaffected by max_recv.
1871 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1872 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1874 if (NT_STATUS_V(status)) {
1877 * We used to make lockread a blocking lock. It turns out
1878 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1882 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1884 * A blocking lock was requested. Package up
1885 * this smb into a queued request and push it
1886 * onto the blocking lock queue.
1888 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1889 (SMB_BIG_UINT)numtoread)) {
1890 END_PROFILE(SMBlockread);
1895 END_PROFILE(SMBlockread);
1896 return ERROR_NT(status);
1900 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1903 if (numtoread > max_recv) {
1904 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1905 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1906 (unsigned int)numtoread, (unsigned int)max_recv ));
1907 numtoread = MIN(numtoread,max_recv);
1909 nread = read_file(fsp,data,startpos,numtoread);
1912 END_PROFILE(SMBlockread);
1913 return(UNIXERROR(ERRDOS,ERRnoaccess));
1917 SSVAL(outbuf,smb_vwv0,nread);
1918 SSVAL(outbuf,smb_vwv5,nread+3);
1919 SSVAL(smb_buf(outbuf),1,nread);
1921 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1922 fsp->fnum, (int)numtoread, (int)nread));
1924 END_PROFILE(SMBlockread);
1928 /****************************************************************************
1930 ****************************************************************************/
1932 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1939 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1940 START_PROFILE(SMBread);
1942 CHECK_FSP(fsp,conn);
1945 numtoread = SVAL(inbuf,smb_vwv1);
1946 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1948 outsize = set_message(outbuf,5,3,True);
1949 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1951 * The requested read size cannot be greater than max_recv. JRA.
1953 if (numtoread > max_recv) {
1954 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1955 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1956 (unsigned int)numtoread, (unsigned int)max_recv ));
1957 numtoread = MIN(numtoread,max_recv);
1960 data = smb_buf(outbuf) + 3;
1962 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1963 END_PROFILE(SMBread);
1964 return ERROR_DOS(ERRDOS,ERRlock);
1968 nread = read_file(fsp,data,startpos,numtoread);
1971 END_PROFILE(SMBread);
1972 return(UNIXERROR(ERRDOS,ERRnoaccess));
1976 SSVAL(outbuf,smb_vwv0,nread);
1977 SSVAL(outbuf,smb_vwv5,nread+3);
1978 SCVAL(smb_buf(outbuf),0,1);
1979 SSVAL(smb_buf(outbuf),1,nread);
1981 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1982 fsp->fnum, (int)numtoread, (int)nread ) );
1984 END_PROFILE(SMBread);
1988 /****************************************************************************
1989 Reply to a read and X - possibly using sendfile.
1990 ****************************************************************************/
1992 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1993 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1996 char *data = smb_buf(outbuf);
1998 #if defined(WITH_SENDFILE)
2000 * We can only use sendfile on a non-chained packet and on a file
2001 * that is exclusively oplocked.
2004 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2005 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2006 SMB_STRUCT_STAT sbuf;
2009 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2010 return(UNIXERROR(ERRDOS,ERRnoaccess));
2012 if (startpos > sbuf.st_size)
2015 if (smb_maxcnt > (sbuf.st_size - startpos))
2016 smb_maxcnt = (sbuf.st_size - startpos);
2018 if (smb_maxcnt == 0)
2022 * Set up the packet header before send. We
2023 * assume here the sendfile will work (get the
2024 * correct amount of data).
2027 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2028 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2029 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2030 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2031 SCVAL(outbuf,smb_vwv0,0xFF);
2032 set_message(outbuf,12,smb_maxcnt,False);
2033 header.data = outbuf;
2034 header.length = data - outbuf;
2037 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2039 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2040 * return ENOSYS then pretend we just got a normal read.
2042 if (errno == ENOSYS)
2045 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2046 fsp->fsp_name, strerror(errno) ));
2047 exit_server("send_file_readX sendfile failed");
2050 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2051 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2059 nread = read_file(fsp,data,startpos,smb_maxcnt);
2062 END_PROFILE(SMBreadX);
2063 return(UNIXERROR(ERRDOS,ERRnoaccess));
2066 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2067 SSVAL(outbuf,smb_vwv5,nread);
2068 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2069 SSVAL(smb_buf(outbuf),-2,nread);
2071 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2072 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2077 /****************************************************************************
2078 Reply to a read and X.
2079 ****************************************************************************/
2081 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2083 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2084 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2086 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2088 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2091 START_PROFILE(SMBreadX);
2093 /* If it's an IPC, pass off the pipe handler. */
2095 END_PROFILE(SMBreadX);
2096 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2099 CHECK_FSP(fsp,conn);
2102 set_message(outbuf,12,0,True);
2104 if(CVAL(inbuf,smb_wct) == 12) {
2105 #ifdef LARGE_SMB_OFF_T
2107 * This is a large offset (64 bit) read.
2109 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2111 #else /* !LARGE_SMB_OFF_T */
2114 * Ensure we haven't been sent a >32 bit offset.
2117 if(IVAL(inbuf,smb_vwv10) != 0) {
2118 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2119 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2120 END_PROFILE(SMBreadX);
2121 return ERROR_DOS(ERRDOS,ERRbadaccess);
2124 #endif /* LARGE_SMB_OFF_T */
2128 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2129 END_PROFILE(SMBreadX);
2130 return ERROR_DOS(ERRDOS,ERRlock);
2133 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2135 nread = chain_reply(inbuf,outbuf,length,bufsize);
2137 END_PROFILE(SMBreadX);
2141 /****************************************************************************
2142 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2143 ****************************************************************************/
2145 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2148 ssize_t total_written=0;
2149 size_t numtowrite=0;
2154 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2156 START_PROFILE(SMBwritebraw);
2158 if (srv_is_signing_active()) {
2159 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2162 CHECK_FSP(fsp,conn);
2165 tcount = IVAL(inbuf,smb_vwv1);
2166 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2167 write_through = BITSETW(inbuf+smb_vwv7,0);
2169 /* We have to deal with slightly different formats depending
2170 on whether we are using the core+ or lanman1.0 protocol */
2172 if(Protocol <= PROTOCOL_COREPLUS) {
2173 numtowrite = SVAL(smb_buf(inbuf),-2);
2174 data = smb_buf(inbuf);
2176 numtowrite = SVAL(inbuf,smb_vwv10);
2177 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2180 /* force the error type */
2181 SCVAL(inbuf,smb_com,SMBwritec);
2182 SCVAL(outbuf,smb_com,SMBwritec);
2184 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2185 END_PROFILE(SMBwritebraw);
2186 return(ERROR_DOS(ERRDOS,ERRlock));
2190 nwritten = write_file(fsp,data,startpos,numtowrite);
2192 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2193 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2195 if (nwritten < (ssize_t)numtowrite) {
2196 END_PROFILE(SMBwritebraw);
2197 return(UNIXERROR(ERRHRD,ERRdiskfull));
2200 total_written = nwritten;
2202 /* Return a message to the redirector to tell it to send more bytes */
2203 SCVAL(outbuf,smb_com,SMBwritebraw);
2204 SSVALS(outbuf,smb_vwv0,-1);
2205 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2206 if (!send_smb(smbd_server_fd(),outbuf))
2207 exit_server("reply_writebraw: send_smb failed.");
2209 /* Now read the raw data into the buffer and write it */
2210 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2211 exit_server("secondary writebraw failed");
2214 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2215 numtowrite = smb_len(inbuf);
2217 /* Set up outbuf to return the correct return */
2218 outsize = set_message(outbuf,1,0,True);
2219 SCVAL(outbuf,smb_com,SMBwritec);
2220 SSVAL(outbuf,smb_vwv0,total_written);
2222 if (numtowrite != 0) {
2224 if (numtowrite > BUFFER_SIZE) {
2225 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2226 (unsigned int)numtowrite ));
2227 exit_server("secondary writebraw failed");
2230 if (tcount > nwritten+numtowrite) {
2231 DEBUG(3,("Client overestimated the write %d %d %d\n",
2232 (int)tcount,(int)nwritten,(int)numtowrite));
2235 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2236 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2238 exit_server("secondary writebraw failed");
2241 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2243 if (nwritten < (ssize_t)numtowrite) {
2244 SCVAL(outbuf,smb_rcls,ERRHRD);
2245 SSVAL(outbuf,smb_err,ERRdiskfull);
2249 total_written += nwritten;
2252 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2253 sync_file(conn,fsp);
2255 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2256 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2258 /* we won't return a status if write through is not selected - this follows what WfWg does */
2259 END_PROFILE(SMBwritebraw);
2260 if (!write_through && total_written==tcount) {
2262 #if RABBIT_PELLET_FIX
2264 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2265 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2267 if (!send_keepalive(smbd_server_fd()))
2268 exit_server("reply_writebraw: send of keepalive failed");
2276 /****************************************************************************
2277 Reply to a writeunlock (core+).
2278 ****************************************************************************/
2280 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2281 int size, int dum_buffsize)
2283 ssize_t nwritten = -1;
2287 NTSTATUS status = NT_STATUS_OK;
2288 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2290 START_PROFILE(SMBwriteunlock);
2292 CHECK_FSP(fsp,conn);
2295 numtowrite = SVAL(inbuf,smb_vwv1);
2296 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2297 data = smb_buf(inbuf) + 3;
2299 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2300 WRITE_LOCK,False)) {
2301 END_PROFILE(SMBwriteunlock);
2302 return ERROR_DOS(ERRDOS,ERRlock);
2305 /* The special X/Open SMB protocol handling of
2306 zero length writes is *NOT* done for
2311 nwritten = write_file(fsp,data,startpos,numtowrite);
2313 if (lp_syncalways(SNUM(conn)))
2314 sync_file(conn,fsp);
2316 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2317 END_PROFILE(SMBwriteunlock);
2318 return(UNIXERROR(ERRHRD,ERRdiskfull));
2322 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2323 (SMB_BIG_UINT)startpos);
2324 if (NT_STATUS_V(status)) {
2325 END_PROFILE(SMBwriteunlock);
2326 return ERROR_NT(status);
2330 outsize = set_message(outbuf,1,0,True);
2332 SSVAL(outbuf,smb_vwv0,nwritten);
2334 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2335 fsp->fnum, (int)numtowrite, (int)nwritten));
2337 END_PROFILE(SMBwriteunlock);
2341 /****************************************************************************
2343 ****************************************************************************/
2345 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2348 ssize_t nwritten = -1;
2351 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2353 START_PROFILE(SMBwrite);
2355 /* If it's an IPC, pass off the pipe handler. */
2357 END_PROFILE(SMBwrite);
2358 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2361 CHECK_FSP(fsp,conn);
2364 numtowrite = SVAL(inbuf,smb_vwv1);
2365 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2366 data = smb_buf(inbuf) + 3;
2368 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2369 END_PROFILE(SMBwrite);
2370 return ERROR_DOS(ERRDOS,ERRlock);
2374 * X/Open SMB protocol says that if smb_vwv1 is
2375 * zero then the file size should be extended or
2376 * truncated to the size given in smb_vwv[2-3].
2379 if(numtowrite == 0) {
2381 * This is actually an allocate call, and set EOF. JRA.
2383 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2385 END_PROFILE(SMBwrite);
2386 return ERROR_NT(NT_STATUS_DISK_FULL);
2388 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2390 END_PROFILE(SMBwrite);
2391 return ERROR_NT(NT_STATUS_DISK_FULL);
2394 nwritten = write_file(fsp,data,startpos,numtowrite);
2396 if (lp_syncalways(SNUM(conn)))
2397 sync_file(conn,fsp);
2399 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2400 END_PROFILE(SMBwrite);
2401 return(UNIXERROR(ERRHRD,ERRdiskfull));
2404 outsize = set_message(outbuf,1,0,True);
2406 SSVAL(outbuf,smb_vwv0,nwritten);
2408 if (nwritten < (ssize_t)numtowrite) {
2409 SCVAL(outbuf,smb_rcls,ERRHRD);
2410 SSVAL(outbuf,smb_err,ERRdiskfull);
2413 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2415 END_PROFILE(SMBwrite);
2419 /****************************************************************************
2420 Reply to a write and X.
2421 ****************************************************************************/
2423 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2425 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2426 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2427 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2428 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2429 ssize_t nwritten = -1;
2430 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2431 unsigned int smblen = smb_len(inbuf);
2433 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2434 START_PROFILE(SMBwriteX);
2436 /* If it's an IPC, pass off the pipe handler. */
2438 END_PROFILE(SMBwriteX);
2439 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2442 CHECK_FSP(fsp,conn);
2445 /* Deal with possible LARGE_WRITEX */
2447 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2449 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2450 END_PROFILE(SMBwriteX);
2451 return ERROR_DOS(ERRDOS,ERRbadmem);
2454 data = smb_base(inbuf) + smb_doff;
2456 if(CVAL(inbuf,smb_wct) == 14) {
2457 #ifdef LARGE_SMB_OFF_T
2459 * This is a large offset (64 bit) write.
2461 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2463 #else /* !LARGE_SMB_OFF_T */
2466 * Ensure we haven't been sent a >32 bit offset.
2469 if(IVAL(inbuf,smb_vwv12) != 0) {
2470 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2471 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2472 END_PROFILE(SMBwriteX);
2473 return ERROR_DOS(ERRDOS,ERRbadaccess);
2476 #endif /* LARGE_SMB_OFF_T */
2479 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2480 END_PROFILE(SMBwriteX);
2481 return ERROR_DOS(ERRDOS,ERRlock);
2484 /* X/Open SMB protocol says that, unlike SMBwrite
2485 if the length is zero then NO truncation is
2486 done, just a write of zero. To truncate a file,
2492 nwritten = write_file(fsp,data,startpos,numtowrite);
2494 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2495 END_PROFILE(SMBwriteX);
2496 return(UNIXERROR(ERRHRD,ERRdiskfull));
2499 set_message(outbuf,6,0,True);
2501 SSVAL(outbuf,smb_vwv2,nwritten);
2503 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2505 if (nwritten < (ssize_t)numtowrite) {
2506 SCVAL(outbuf,smb_rcls,ERRHRD);
2507 SSVAL(outbuf,smb_err,ERRdiskfull);
2510 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2511 fsp->fnum, (int)numtowrite, (int)nwritten));
2513 if (lp_syncalways(SNUM(conn)) || write_through)
2514 sync_file(conn,fsp);
2516 END_PROFILE(SMBwriteX);
2517 return chain_reply(inbuf,outbuf,length,bufsize);
2520 /****************************************************************************
2522 ****************************************************************************/
2524 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2530 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2531 START_PROFILE(SMBlseek);
2533 CHECK_FSP(fsp,conn);
2535 flush_write_cache(fsp, SEEK_FLUSH);
2537 mode = SVAL(inbuf,smb_vwv1) & 3;
2538 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2539 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2548 res = fsp->pos + startpos;
2559 if (umode == SEEK_END) {
2560 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2561 if(errno == EINVAL) {
2562 SMB_OFF_T current_pos = startpos;
2563 SMB_STRUCT_STAT sbuf;
2565 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2566 END_PROFILE(SMBlseek);
2567 return(UNIXERROR(ERRDOS,ERRnoaccess));
2570 current_pos += sbuf.st_size;
2572 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2577 END_PROFILE(SMBlseek);
2578 return(UNIXERROR(ERRDOS,ERRnoaccess));
2584 outsize = set_message(outbuf,2,0,True);
2585 SIVAL(outbuf,smb_vwv0,res);
2587 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2588 fsp->fnum, (double)startpos, (double)res, mode));
2590 END_PROFILE(SMBlseek);
2594 /****************************************************************************
2596 ****************************************************************************/
2598 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2600 int outsize = set_message(outbuf,0,0,True);
2601 uint16 fnum = SVAL(inbuf,smb_vwv0);
2602 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2603 START_PROFILE(SMBflush);
2606 CHECK_FSP(fsp,conn);
2609 file_sync_all(conn);
2611 sync_file(conn,fsp);
2614 DEBUG(3,("flush\n"));
2615 END_PROFILE(SMBflush);
2619 /****************************************************************************
2621 ****************************************************************************/
2623 int reply_exit(connection_struct *conn,
2624 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2627 START_PROFILE(SMBexit);
2629 file_close_pid(SVAL(inbuf,smb_pid));
2631 outsize = set_message(outbuf,0,0,True);
2633 DEBUG(3,("exit\n"));
2635 END_PROFILE(SMBexit);
2639 /****************************************************************************
2640 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2641 ****************************************************************************/
2643 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2646 extern struct current_user current_user;
2649 int32 eclass = 0, err = 0;
2650 files_struct *fsp = NULL;
2651 START_PROFILE(SMBclose);
2653 outsize = set_message(outbuf,0,0,True);
2655 /* If it's an IPC, pass off to the pipe handler. */
2657 END_PROFILE(SMBclose);
2658 return reply_pipe_close(conn, inbuf,outbuf);
2661 fsp = file_fsp(inbuf,smb_vwv0);
2664 * We can only use CHECK_FSP if we know it's not a directory.
2667 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2668 END_PROFILE(SMBclose);
2669 return ERROR_DOS(ERRDOS,ERRbadfid);
2672 if(fsp->is_directory) {
2674 * Special case - close NT SMB directory handle.
2676 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2677 close_file(fsp,True);
2680 * Close ordinary file.
2685 /* Save the name for time set in close. */
2686 pstrcpy( file_name, fsp->fsp_name);
2688 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2690 conn->num_files_open));
2693 * close_file() returns the unix errno if an error
2694 * was detected on close - normally this is due to
2695 * a disk full error. If not then it was probably an I/O error.
2698 if((close_err = close_file(fsp,True)) != 0) {
2700 END_PROFILE(SMBclose);
2701 return (UNIXERROR(ERRHRD,ERRgeneral));
2705 * Now take care of any time sent in the close.
2708 mtime = make_unix_date3(inbuf+smb_vwv1);
2710 /* try and set the date */
2711 set_filetime(conn, file_name, mtime);
2715 /* We have a cached error */
2717 END_PROFILE(SMBclose);
2718 return ERROR_DOS(eclass,err);
2721 END_PROFILE(SMBclose);
2725 /****************************************************************************
2726 Reply to a writeclose (Core+ protocol).
2727 ****************************************************************************/
2729 int reply_writeclose(connection_struct *conn,
2730 char *inbuf,char *outbuf, int size, int dum_buffsize)
2733 ssize_t nwritten = -1;
2739 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2740 START_PROFILE(SMBwriteclose);
2742 CHECK_FSP(fsp,conn);
2745 numtowrite = SVAL(inbuf,smb_vwv1);
2746 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2747 mtime = make_unix_date3(inbuf+smb_vwv4);
2748 data = smb_buf(inbuf) + 1;
2750 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2751 END_PROFILE(SMBwriteclose);
2752 return ERROR_DOS(ERRDOS,ERRlock);
2755 nwritten = write_file(fsp,data,startpos,numtowrite);
2757 set_filetime(conn, fsp->fsp_name,mtime);
2760 * More insanity. W2K only closes the file if writelen > 0.
2765 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2767 close_err = close_file(fsp,True);
2770 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2771 fsp->fnum, (int)numtowrite, (int)nwritten,
2772 conn->num_files_open));
2774 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2775 END_PROFILE(SMBwriteclose);
2776 return(UNIXERROR(ERRHRD,ERRdiskfull));
2779 if(close_err != 0) {
2781 END_PROFILE(SMBwriteclose);
2782 return(UNIXERROR(ERRHRD,ERRgeneral));
2785 outsize = set_message(outbuf,1,0,True);
2787 SSVAL(outbuf,smb_vwv0,nwritten);
2788 END_PROFILE(SMBwriteclose);
2792 /****************************************************************************
2794 ****************************************************************************/
2796 int reply_lock(connection_struct *conn,
2797 char *inbuf,char *outbuf, int length, int dum_buffsize)
2799 int outsize = set_message(outbuf,0,0,True);
2800 SMB_BIG_UINT count,offset;
2802 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2803 BOOL my_lock_ctx = False;
2805 START_PROFILE(SMBlock);
2807 CHECK_FSP(fsp,conn);
2809 release_level_2_oplocks_on_change(fsp);
2811 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2812 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2814 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2815 fsp->fd, fsp->fnum, (double)offset, (double)count));
2817 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2818 if (NT_STATUS_V(status)) {
2820 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2821 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2823 * A blocking lock was requested. Package up
2824 * this smb into a queued request and push it
2825 * onto the blocking lock queue.
2827 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2828 END_PROFILE(SMBlock);
2833 END_PROFILE(SMBlock);
2834 return ERROR_NT(status);
2837 END_PROFILE(SMBlock);
2841 /****************************************************************************
2843 ****************************************************************************/
2845 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2848 int outsize = set_message(outbuf,0,0,True);
2849 SMB_BIG_UINT count,offset;
2851 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2852 START_PROFILE(SMBunlock);
2854 CHECK_FSP(fsp,conn);
2856 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2857 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2859 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2860 if (NT_STATUS_V(status)) {
2861 END_PROFILE(SMBunlock);
2862 return ERROR_NT(status);
2865 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2866 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2868 END_PROFILE(SMBunlock);
2872 /****************************************************************************
2874 ****************************************************************************/
2876 int reply_tdis(connection_struct *conn,
2877 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2879 int outsize = set_message(outbuf,0,0,True);
2881 START_PROFILE(SMBtdis);
2883 vuid = SVAL(inbuf,smb_uid);
2886 DEBUG(4,("Invalid connection in tdis\n"));
2887 END_PROFILE(SMBtdis);
2888 return ERROR_DOS(ERRSRV,ERRinvnid);
2893 close_cnum(conn,vuid);
2895 END_PROFILE(SMBtdis);
2899 /****************************************************************************
2901 ****************************************************************************/
2903 int reply_echo(connection_struct *conn,
2904 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2906 int smb_reverb = SVAL(inbuf,smb_vwv0);
2908 unsigned int data_len = smb_buflen(inbuf);
2909 int outsize = set_message(outbuf,1,data_len,True);
2910 START_PROFILE(SMBecho);
2912 if (data_len > BUFFER_SIZE) {
2913 DEBUG(0,("reply_echo: data_len too large.\n"));
2914 END_PROFILE(SMBecho);
2918 /* copy any incoming data back out */
2920 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2922 if (smb_reverb > 100) {
2923 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2927 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2928 SSVAL(outbuf,smb_vwv0,seq_num);
2930 smb_setlen(outbuf,outsize - 4);
2932 if (!send_smb(smbd_server_fd(),outbuf))
2933 exit_server("reply_echo: send_smb failed.");
2936 DEBUG(3,("echo %d times\n", smb_reverb));
2940 END_PROFILE(SMBecho);
2944 /****************************************************************************
2945 Reply to a printopen.
2946 ****************************************************************************/
2948 int reply_printopen(connection_struct *conn,
2949 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2953 START_PROFILE(SMBsplopen);
2955 if (!CAN_PRINT(conn)) {
2956 END_PROFILE(SMBsplopen);
2957 return ERROR_DOS(ERRDOS,ERRnoaccess);
2960 /* Open for exclusive use, write only. */
2961 fsp = print_fsp_open(conn, NULL);
2964 END_PROFILE(SMBsplopen);
2965 return(UNIXERROR(ERRDOS,ERRnoaccess));
2968 outsize = set_message(outbuf,1,0,True);
2969 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2971 DEBUG(3,("openprint fd=%d fnum=%d\n",
2972 fsp->fd, fsp->fnum));
2974 END_PROFILE(SMBsplopen);
2978 /****************************************************************************
2979 Reply to a printclose.
2980 ****************************************************************************/
2982 int reply_printclose(connection_struct *conn,
2983 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2985 int outsize = set_message(outbuf,0,0,True);
2986 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2988 START_PROFILE(SMBsplclose);
2990 CHECK_FSP(fsp,conn);
2992 if (!CAN_PRINT(conn)) {
2993 END_PROFILE(SMBsplclose);
2994 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2997 DEBUG(3,("printclose fd=%d fnum=%d\n",
2998 fsp->fd,fsp->fnum));
3000 close_err = close_file(fsp,True);
3002 if(close_err != 0) {
3004 END_PROFILE(SMBsplclose);
3005 return(UNIXERROR(ERRHRD,ERRgeneral));
3008 END_PROFILE(SMBsplclose);
3012 /****************************************************************************
3013 Reply to a printqueue.
3014 ****************************************************************************/
3016 int reply_printqueue(connection_struct *conn,
3017 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3019 int outsize = set_message(outbuf,2,3,True);
3020 int max_count = SVAL(inbuf,smb_vwv0);
3021 int start_index = SVAL(inbuf,smb_vwv1);
3022 START_PROFILE(SMBsplretq);
3024 /* we used to allow the client to get the cnum wrong, but that
3025 is really quite gross and only worked when there was only
3026 one printer - I think we should now only accept it if they
3027 get it right (tridge) */
3028 if (!CAN_PRINT(conn)) {
3029 END_PROFILE(SMBsplretq);
3030 return ERROR_DOS(ERRDOS,ERRnoaccess);
3033 SSVAL(outbuf,smb_vwv0,0);
3034 SSVAL(outbuf,smb_vwv1,0);
3035 SCVAL(smb_buf(outbuf),0,1);
3036 SSVAL(smb_buf(outbuf),1,0);
3038 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3039 start_index, max_count));
3042 print_queue_struct *queue = NULL;
3043 print_status_struct status;
3044 char *p = smb_buf(outbuf) + 3;
3045 int count = print_queue_status(SNUM(conn), &queue, &status);
3046 int num_to_get = ABS(max_count);
3047 int first = (max_count>0?start_index:start_index+max_count+1);
3053 num_to_get = MIN(num_to_get,count-first);
3056 for (i=first;i<first+num_to_get;i++) {
3057 put_dos_date2(p,0,queue[i].time);
3058 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3059 SSVAL(p,5, queue[i].job);
3060 SIVAL(p,7,queue[i].size);
3062 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3067 outsize = set_message(outbuf,2,28*count+3,False);
3068 SSVAL(outbuf,smb_vwv0,count);
3069 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3070 SCVAL(smb_buf(outbuf),0,1);
3071 SSVAL(smb_buf(outbuf),1,28*count);
3076 DEBUG(3,("%d entries returned in queue\n",count));
3079 END_PROFILE(SMBsplretq);
3083 /****************************************************************************
3084 Reply to a printwrite.
3085 ****************************************************************************/
3087 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3090 int outsize = set_message(outbuf,0,0,True);
3092 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3094 START_PROFILE(SMBsplwr);
3096 if (!CAN_PRINT(conn)) {
3097 END_PROFILE(SMBsplwr);
3098 return ERROR_DOS(ERRDOS,ERRnoaccess);
3101 CHECK_FSP(fsp,conn);
3104 numtowrite = SVAL(smb_buf(inbuf),1);
3105 data = smb_buf(inbuf) + 3;
3107 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3108 END_PROFILE(SMBsplwr);
3109 return(UNIXERROR(ERRHRD,ERRdiskfull));
3112 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3114 END_PROFILE(SMBsplwr);
3118 /****************************************************************************
3119 The guts of the mkdir command, split out so it may be called by the NT SMB
3121 ****************************************************************************/
3123 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3125 BOOL bad_path = False;
3126 SMB_STRUCT_STAT sbuf;
3129 unix_convert(directory,conn,0,&bad_path,&sbuf);
3131 if( strchr_m(directory, ':')) {
3132 return NT_STATUS_NOT_A_DIRECTORY;
3135 if (ms_has_wild(directory)) {
3136 return NT_STATUS_OBJECT_NAME_INVALID;
3139 if (check_name(directory, conn))
3140 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3143 if(errno == ENOENT) {
3145 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3147 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3149 return map_nt_error_from_unix(errno);
3152 return NT_STATUS_OK;
3155 /****************************************************************************
3157 ****************************************************************************/
3159 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3164 START_PROFILE(SMBmkdir);
3166 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3167 if (!NT_STATUS_IS_OK(status)) {
3168 END_PROFILE(SMBmkdir);
3169 return ERROR_NT(status);
3172 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3174 status = mkdir_internal(conn, directory);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 END_PROFILE(SMBmkdir);
3177 return ERROR_NT(status);
3180 outsize = set_message(outbuf,0,0,True);
3182 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3184 END_PROFILE(SMBmkdir);
3188 /****************************************************************************
3189 Static function used by reply_rmdir to delete an entire directory
3190 tree recursively. Return False on ok, True on fail.
3191 ****************************************************************************/
3193 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3195 const char *dname = NULL;
3197 void *dirptr = OpenDir(conn, directory, False);
3202 while((dname = ReadDirName(dirptr))) {
3206 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3209 /* Construct the full name. */
3210 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3216 pstrcpy(fullname, directory);
3217 pstrcat(fullname, "/");
3218 pstrcat(fullname, dname);
3220 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3225 if(st.st_mode & S_IFDIR) {
3226 if(recursive_rmdir(conn, fullname)!=0) {
3230 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3234 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3243 /****************************************************************************
3244 The internals of the rmdir code - called elsewhere.
3245 ****************************************************************************/
3247 BOOL rmdir_internals(connection_struct *conn, char *directory)
3251 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3252 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3254 * Check to see if the only thing in this directory are
3255 * vetoed files/directories. If so then delete them and
3256 * retry. If we fail to delete any of them (and we *don't*
3257 * do a recursive delete) then fail the rmdir.
3259 BOOL all_veto_files = True;
3261 void *dirptr = OpenDir(conn, directory, False);
3263 if(dirptr != NULL) {
3264 int dirpos = TellDir(dirptr);
3265 while ((dname = ReadDirName(dirptr))) {
3266 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3268 if(!IS_VETO_PATH(conn, dname)) {
3269 all_veto_files = False;
3274 if(all_veto_files) {
3275 SeekDir(dirptr,dirpos);
3276 while ((dname = ReadDirName(dirptr))) {
3280 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3283 /* Construct the full name. */
3284 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3289 pstrcpy(fullname, directory);
3290 pstrcat(fullname, "/");
3291 pstrcat(fullname, dname);
3293 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3295 if(st.st_mode & S_IFDIR) {
3296 if(lp_recursive_veto_delete(SNUM(conn))) {
3297 if(recursive_rmdir(conn, fullname) != 0)
3300 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3302 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3306 /* Retry the rmdir */
3307 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3317 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3322 /****************************************************************************
3324 ****************************************************************************/
3326 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3331 BOOL bad_path = False;
3332 SMB_STRUCT_STAT sbuf;
3334 START_PROFILE(SMBrmdir);
3336 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3337 if (!NT_STATUS_IS_OK(status)) {
3338 END_PROFILE(SMBrmdir);
3339 return ERROR_NT(status);
3342 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3344 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3346 if (check_name(directory,conn)) {
3347 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3348 ok = rmdir_internals(conn, directory);
3352 END_PROFILE(SMBrmdir);
3353 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3356 outsize = set_message(outbuf,0,0,True);
3358 DEBUG( 3, ( "rmdir %s\n", directory ) );
3360 END_PROFILE(SMBrmdir);
3364 /*******************************************************************
3365 Resolve wildcards in a filename rename.
3366 Note that name is in UNIX charset and thus potentially can be more
3367 than fstring buffer (255 bytes) especially in default UTF-8 case.
3368 Therefore, we use pstring inside and all calls should ensure that
3369 name2 is at least pstring-long (they do already)
3370 ********************************************************************/
3372 static BOOL resolve_wildcards(const char *name1, char *name2)
3374 pstring root1,root2;
3376 char *p,*p2, *pname1, *pname2;
3377 int available_space, actual_space;
3380 pname1 = strrchr_m(name1,'/');
3381 pname2 = strrchr_m(name2,'/');
3383 if (!pname1 || !pname2)
3386 pstrcpy(root1,pname1);
3387 pstrcpy(root2,pname2);
3388 p = strrchr_m(root1,'.');
3395 p = strrchr_m(root2,'.');
3409 } else if (*p2 == '*') {
3425 } else if (*p2 == '*') {
3435 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3438 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3439 if (actual_space >= available_space - 1) {
3440 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3441 actual_space - available_space));
3444 pstrcpy_base(pname2, root2, name2);
3450 /****************************************************************************
3451 Ensure open files have their names updates.
3452 ****************************************************************************/
3454 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3457 BOOL did_rename = False;
3459 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3460 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3461 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3462 fsp->fsp_name, newname ));
3463 string_set(&fsp->fsp_name, newname);
3468 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3469 (unsigned int)dev, (double)inode, newname ));
3472 /****************************************************************************
3473 Rename an open file - given an fsp.
3474 ****************************************************************************/
3476 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3478 SMB_STRUCT_STAT sbuf;
3479 BOOL bad_path = False;
3480 pstring newname_last_component;
3481 NTSTATUS error = NT_STATUS_OK;
3486 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3488 /* Quick check for "." and ".." */
3489 if (!bad_path && newname_last_component[0] == '.') {
3490 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3491 return NT_STATUS_ACCESS_DENIED;
3494 if (!rcdest && bad_path) {
3495 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3498 /* Ensure newname contains a '/' */
3499 if(strrchr_m(newname,'/') == 0) {
3502 pstrcpy(tmpstr, "./");
3503 pstrcat(tmpstr, newname);
3504 pstrcpy(newname, tmpstr);
3508 * Check for special case with case preserving and not
3509 * case sensitive. If the old last component differs from the original
3510 * last component only by case, then we should allow
3511 * the rename (user is trying to change the case of the
3515 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3516 strequal(newname, fsp->fsp_name)) {
3518 pstring newname_modified_last_component;
3521 * Get the last component of the modified name.
3522 * Note that we guarantee that newname contains a '/'
3525 p = strrchr_m(newname,'/');
3526 pstrcpy(newname_modified_last_component,p+1);
3528 if(strcsequal(newname_modified_last_component,
3529 newname_last_component) == False) {
3531 * Replace the modified last component with
3534 pstrcpy(p+1, newname_last_component);
3539 * If the src and dest names are identical - including case,
3540 * don't do the rename, just return success.
3543 if (strcsequal(fsp->fsp_name, newname)) {
3544 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3546 return NT_STATUS_OK;
3549 dest_exists = vfs_object_exist(conn,newname,NULL);
3551 if(!replace_if_exists && dest_exists) {
3552 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3553 fsp->fsp_name,newname));
3554 return NT_STATUS_OBJECT_NAME_COLLISION;
3557 error = can_rename(newname,conn,&sbuf);
3559 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3560 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3561 nt_errstr(error), fsp->fsp_name,newname));
3562 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3563 error = NT_STATUS_ACCESS_DENIED;
3567 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3568 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3569 fsp->fsp_name,newname));
3570 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3571 return NT_STATUS_OK;
3574 if (errno == ENOTDIR || errno == EISDIR)
3575 error = NT_STATUS_OBJECT_NAME_COLLISION;
3577 error = map_nt_error_from_unix(errno);
3579 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3580 nt_errstr(error), fsp->fsp_name,newname));
3585 /****************************************************************************
3586 The guts of the rename command, split out so it may be called by the NT SMB
3588 ****************************************************************************/
3590 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3594 pstring last_component_src;
3595 pstring last_component_dest;
3598 BOOL bad_path_src = False;
3599 BOOL bad_path_dest = False;
3601 NTSTATUS error = NT_STATUS_OK;
3604 SMB_STRUCT_STAT sbuf1, sbuf2;
3606 *directory = *mask = 0;
3611 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3612 if (!rc && bad_path_src) {
3613 if (ms_has_wild(last_component_src))
3614 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3615 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3618 /* Quick check for "." and ".." */
3619 if (last_component_src[0] == '.') {
3620 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3621 return NT_STATUS_OBJECT_NAME_INVALID;
3625 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3627 /* Quick check for "." and ".." */
3628 if (last_component_dest[0] == '.') {
3629 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3630 return NT_STATUS_OBJECT_NAME_INVALID;
3635 * Split the old name into directory and last component
3636 * strings. Note that unix_convert may have stripped off a
3637 * leading ./ from both name and newname if the rename is
3638 * at the root of the share. We need to make sure either both
3639 * name and newname contain a / character or neither of them do
3640 * as this is checked in resolve_wildcards().
3643 p = strrchr_m(name,'/');
3645 pstrcpy(directory,".");
3649 pstrcpy(directory,name);
3651 *p = '/'; /* Replace needed for exceptional test below. */
3655 * We should only check the mangled cache
3656 * here if unix_convert failed. This means
3657 * that the path in 'mask' doesn't exist
3658 * on the file system and so we need to look
3659 * for a possible mangle. This patch from
3660 * Tine Smukavec <valentin.smukavec@hermes.si>.
3663 if (!rc && mangle_is_mangled(mask))
3664 mangle_check_cache( mask );
3666 has_wild = ms_has_wild(mask);
3670 * No wildcards - just process the one file.
3672 BOOL is_short_name = mangle_is_8_3(name, True);
3674 /* Add a terminating '/' to the directory name. */
3675 pstrcat(directory,"/");
3676 pstrcat(directory,mask);
3678 /* Ensure newname contains a '/' also */
3679 if(strrchr_m(newname,'/') == 0) {
3682 pstrcpy(tmpstr, "./");
3683 pstrcat(tmpstr, newname);
3684 pstrcpy(newname, tmpstr);
3687 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3688 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3689 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3690 newname, last_component_dest, is_short_name));
3693 * Check for special case with case preserving and not
3694 * case sensitive, if directory and newname are identical,
3695 * and the old last component differs from the original
3696 * last component only by case, then we should allow
3697 * the rename (user is trying to change the case of the
3700 if((conn->case_sensitive == False) &&
3701 (((conn->case_preserve == True) &&
3702 (is_short_name == False)) ||
3703 ((conn->short_case_preserve == True) &&
3704 (is_short_name == True))) &&
3705 strcsequal(directory, newname)) {
3706 pstring modified_last_component;
3709 * Get the last component of the modified name.
3710 * Note that we guarantee that newname contains a '/'
3713 p = strrchr_m(newname,'/');
3714 pstrcpy(modified_last_component,p+1);
3716 if(strcsequal(modified_last_component,
3717 last_component_dest) == False) {
3719 * Replace the modified last component with
3722 pstrcpy(p+1, last_component_dest);
3726 resolve_wildcards(directory,newname);
3729 * The source object must exist.
3732 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3733 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3734 directory,newname));
3736 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3738 * Must return different errors depending on whether the parent
3739 * directory existed or not.
3742 p = strrchr_m(directory, '/');
3744 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3746 if (vfs_object_exist(conn, directory, NULL))
3747 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3748 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3750 error = map_nt_error_from_unix(errno);
3751 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3752 nt_errstr(error), directory,newname));
3757 if (!rcdest && bad_path_dest) {
3758 if (ms_has_wild(last_component_dest))
3759 return NT_STATUS_OBJECT_NAME_INVALID;
3760 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3763 error = can_rename(directory,conn,&sbuf1);
3765 if (!NT_STATUS_IS_OK(error)) {
3766 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3767 nt_errstr(error), directory,newname));
3772 * If the src and dest names are identical - including case,
3773 * don't do the rename, just return success.
3776 if (strcsequal(directory, newname)) {
3777 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3778 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3779 return NT_STATUS_OK;
3782 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3783 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3784 directory,newname));
3785 return NT_STATUS_OBJECT_NAME_COLLISION;
3788 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3789 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3790 directory,newname));
3791 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3792 return NT_STATUS_OK;
3795 if (errno == ENOTDIR || errno == EISDIR)
3796 error = NT_STATUS_OBJECT_NAME_COLLISION;
3798 error = map_nt_error_from_unix(errno);
3800 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3801 nt_errstr(error), directory,newname));
3806 * Wildcards - process each file that matches.
3808 void *dirptr = NULL;
3812 if (check_name(directory,conn))
3813 dirptr = OpenDir(conn, directory, True);
3816 error = NT_STATUS_NO_SUCH_FILE;
3817 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3819 if (strequal(mask,"????????.???"))
3822 while ((dname = ReadDirName(dirptr))) {
3824 BOOL sysdir_entry = False;
3826 pstrcpy(fname,dname);
3828 /* Quick check for "." and ".." */
3829 if (fname[0] == '.') {
3830 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3832 sysdir_entry = True;
3839 if(!mask_match(fname, mask, conn->case_sensitive))
3843 error = NT_STATUS_OBJECT_NAME_INVALID;
3847 error = NT_STATUS_ACCESS_DENIED;
3848 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3849 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3850 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3851 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3854 error = can_rename(fname,conn,&sbuf1);
3855 if (!NT_STATUS_IS_OK(error)) {
3856 DEBUG(6,("rename %s refused\n", fname));
3859 pstrcpy(destname,newname);
3861 if (!resolve_wildcards(fname,destname)) {
3862 DEBUG(6,("resolve_wildcards %s %s failed\n",
3867 if (strcsequal(fname,destname)) {
3868 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3869 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3871 error = NT_STATUS_OK;
3875 if (!replace_if_exists &&
3876 vfs_file_exist(conn,destname, NULL)) {
3877 DEBUG(6,("file_exist %s\n", destname));
3878 error = NT_STATUS_OBJECT_NAME_COLLISION;
3882 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3883 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3885 error = NT_STATUS_OK;
3887 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3892 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3893 if (!rcdest && bad_path_dest) {
3894 if (ms_has_wild(last_component_dest))
3895 return NT_STATUS_OBJECT_NAME_INVALID;
3896 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3901 if (count == 0 && NT_STATUS_IS_OK(error)) {
3902 error = map_nt_error_from_unix(errno);
3908 /****************************************************************************
3910 ****************************************************************************/
3912 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3919 uint16 attrs = SVAL(inbuf,smb_vwv0);
3922 START_PROFILE(SMBmv);
3924 p = smb_buf(inbuf) + 1;
3925 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3926 if (!NT_STATUS_IS_OK(status)) {
3928 return ERROR_NT(status);
3931 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3932 if (!NT_STATUS_IS_OK(status)) {
3934 return ERROR_NT(status);
3937 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3938 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3940 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3942 status = rename_internals(conn, name, newname, attrs, False);
3943 if (!NT_STATUS_IS_OK(status)) {
3945 return ERROR_NT(status);
3949 * Win2k needs a changenotify request response before it will
3950 * update after a rename..
3952 process_pending_change_notify_queue((time_t)0);
3953 outsize = set_message(outbuf,0,0,True);
3959 /*******************************************************************
3960 Copy a file as part of a reply_copy.
3961 ******************************************************************/
3963 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3964 int count,BOOL target_is_directory, int *err_ret)
3967 SMB_STRUCT_STAT src_sbuf, sbuf2;
3969 files_struct *fsp1,*fsp2;
3975 pstrcpy(dest,dest1);
3976 if (target_is_directory) {
3977 char *p = strrchr_m(src,'/');
3986 if (!vfs_file_exist(conn,src,&src_sbuf))
3989 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3990 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
3995 if (!target_is_directory && count)
3996 ofun = FILE_EXISTS_OPEN;
3998 dosattrs = dos_mode(conn, src, &src_sbuf);
3999 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4000 ZERO_STRUCTP(&sbuf2);
4002 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4003 ofun,dosattrs,0,&Access,&action);
4006 close_file(fsp1,False);
4010 if ((ofun&3) == 1) {
4011 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4012 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4014 * Stop the copy from occurring.
4017 src_sbuf.st_size = 0;
4021 if (src_sbuf.st_size)
4022 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4024 close_file(fsp1,False);
4026 /* Ensure the modtime is set correctly on the destination file. */
4027 fsp2->pending_modtime = src_sbuf.st_mtime;
4030 * As we are opening fsp1 read-only we only expect
4031 * an error on close on fsp2 if we are out of space.
4032 * Thus we don't look at the error return from the
4035 *err_ret = close_file(fsp2,False);
4037 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4040 /****************************************************************************
4041 Reply to a file copy.
4042 ****************************************************************************/
4044 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4049 pstring mask,newname;
4052 int error = ERRnoaccess;
4056 int tid2 = SVAL(inbuf,smb_vwv0);
4057 int ofun = SVAL(inbuf,smb_vwv1);
4058 int flags = SVAL(inbuf,smb_vwv2);
4059 BOOL target_is_directory=False;
4060 BOOL bad_path1 = False;
4061 BOOL bad_path2 = False;
4063 SMB_STRUCT_STAT sbuf1, sbuf2;
4066 START_PROFILE(SMBcopy);
4068 *directory = *mask = 0;
4071 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4072 if (!NT_STATUS_IS_OK(status)) {
4073 END_PROFILE(SMBcopy);
4074 return ERROR_NT(status);
4076 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4077 if (!NT_STATUS_IS_OK(status)) {
4078 END_PROFILE(SMBcopy);
4079 return ERROR_NT(status);
4082 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4084 if (tid2 != conn->cnum) {
4085 /* can't currently handle inter share copies XXXX */
4086 DEBUG(3,("Rejecting inter-share copy\n"));
4087 END_PROFILE(SMBcopy);
4088 return ERROR_DOS(ERRSRV,ERRinvdevice);
4091 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4092 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4094 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4095 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4097 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4099 if ((flags&1) && target_is_directory) {
4100 END_PROFILE(SMBcopy);
4101 return ERROR_DOS(ERRDOS,ERRbadfile);
4104 if ((flags&2) && !target_is_directory) {
4105 END_PROFILE(SMBcopy);
4106 return ERROR_DOS(ERRDOS,ERRbadpath);
4109 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4110 /* wants a tree copy! XXXX */
4111 DEBUG(3,("Rejecting tree copy\n"));
4112 END_PROFILE(SMBcopy);
4113 return ERROR_DOS(ERRSRV,ERRerror);
4116 p = strrchr_m(name,'/');
4118 pstrcpy(directory,"./");
4122 pstrcpy(directory,name);
4127 * We should only check the mangled cache
4128 * here if unix_convert failed. This means
4129 * that the path in 'mask' doesn't exist
4130 * on the file system and so we need to look
4131 * for a possible mangle. This patch from
4132 * Tine Smukavec <valentin.smukavec@hermes.si>.
4135 if (!rc && mangle_is_mangled(mask))
4136 mangle_check_cache( mask );
4138 has_wild = ms_has_wild(mask);
4141 pstrcat(directory,"/");
4142 pstrcat(directory,mask);
4143 if (resolve_wildcards(directory,newname) &&
4144 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4148 END_PROFILE(SMBcopy);
4149 return(UNIXERROR(ERRHRD,ERRgeneral));
4152 exists = vfs_file_exist(conn,directory,NULL);
4155 void *dirptr = NULL;
4159 if (check_name(directory,conn))
4160 dirptr = OpenDir(conn, directory, True);
4165 if (strequal(mask,"????????.???"))
4168 while ((dname = ReadDirName(dirptr))) {
4170 pstrcpy(fname,dname);
4172 if(!mask_match(fname, mask, conn->case_sensitive))
4175 error = ERRnoaccess;
4176 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4177 pstrcpy(destname,newname);
4178 if (resolve_wildcards(fname,destname) &&
4179 copy_file(fname,destname,conn,ofun,
4180 count,target_is_directory,&err))
4182 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4190 /* Error on close... */
4192 END_PROFILE(SMBcopy);
4193 return(UNIXERROR(ERRHRD,ERRgeneral));
4197 END_PROFILE(SMBcopy);
4198 return ERROR_DOS(ERRDOS,error);
4200 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4201 unix_ERR_class = ERRDOS;
4202 unix_ERR_code = ERRbadpath;
4204 END_PROFILE(SMBcopy);
4205 return(UNIXERROR(ERRDOS,error));
4209 outsize = set_message(outbuf,1,0,True);
4210 SSVAL(outbuf,smb_vwv0,count);
4212 END_PROFILE(SMBcopy);
4216 /****************************************************************************
4218 ****************************************************************************/
4220 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4228 START_PROFILE(pathworks_setdir);
4231 if (!CAN_SETDIR(snum)) {
4232 END_PROFILE(pathworks_setdir);
4233 return ERROR_DOS(ERRDOS,ERRnoaccess);
4236 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4237 if (!NT_STATUS_IS_OK(status)) {
4238 END_PROFILE(pathworks_setdir);
4239 return ERROR_NT(status);
4242 if (strlen(newdir) == 0) {
4245 ok = vfs_directory_exist(conn,newdir,NULL);
4247 string_set(&conn->connectpath,newdir);
4251 END_PROFILE(pathworks_setdir);
4252 return ERROR_DOS(ERRDOS,ERRbadpath);
4255 outsize = set_message(outbuf,0,0,True);
4256 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4258 DEBUG(3,("setdir %s\n", newdir));
4260 END_PROFILE(pathworks_setdir);
4264 /****************************************************************************
4265 Get a lock pid, dealing with large count requests.
4266 ****************************************************************************/
4268 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4270 if(!large_file_format)
4271 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4273 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4276 /****************************************************************************
4277 Get a lock count, dealing with large count requests.
4278 ****************************************************************************/
4280 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4282 SMB_BIG_UINT count = 0;
4284 if(!large_file_format) {
4285 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4288 #if defined(HAVE_LONGLONG)
4289 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4290 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4291 #else /* HAVE_LONGLONG */
4294 * NT4.x seems to be broken in that it sends large file (64 bit)
4295 * lockingX calls even if the CAP_LARGE_FILES was *not*
4296 * negotiated. For boxes without large unsigned ints truncate the
4297 * lock count by dropping the top 32 bits.
4300 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4301 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4302 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4303 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4304 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4307 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4308 #endif /* HAVE_LONGLONG */
4314 #if !defined(HAVE_LONGLONG)
4315 /****************************************************************************
4316 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4317 ****************************************************************************/
4319 static uint32 map_lock_offset(uint32 high, uint32 low)
4323 uint32 highcopy = high;
4326 * Try and find out how many significant bits there are in high.
4329 for(i = 0; highcopy; i++)
4333 * We use 31 bits not 32 here as POSIX
4334 * lock offsets may not be negative.
4337 mask = (~0) << (31 - i);
4340 return 0; /* Fail. */
4346 #endif /* !defined(HAVE_LONGLONG) */
4348 /****************************************************************************
4349 Get a lock offset, dealing with large offset requests.
4350 ****************************************************************************/
4352 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4354 SMB_BIG_UINT offset = 0;
4358 if(!large_file_format) {
4359 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4362 #if defined(HAVE_LONGLONG)
4363 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4364 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4365 #else /* HAVE_LONGLONG */
4368 * NT4.x seems to be broken in that it sends large file (64 bit)
4369 * lockingX calls even if the CAP_LARGE_FILES was *not*
4370 * negotiated. For boxes without large unsigned ints mangle the
4371 * lock offset by mapping the top 32 bits onto the lower 32.
4374 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4375 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4376 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4379 if((new_low = map_lock_offset(high, low)) == 0) {
4381 return (SMB_BIG_UINT)-1;
4384 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4385 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4386 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4387 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4390 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4391 #endif /* HAVE_LONGLONG */
4397 /****************************************************************************
4398 Reply to a lockingX request.
4399 ****************************************************************************/
4401 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4403 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4404 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4405 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4406 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4407 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4408 SMB_BIG_UINT count = 0, offset = 0;
4410 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4413 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4415 BOOL my_lock_ctx = False;
4418 START_PROFILE(SMBlockingX);
4420 CHECK_FSP(fsp,conn);
4422 data = smb_buf(inbuf);
4424 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4425 /* we don't support these - and CANCEL_LOCK makes w2k
4426 and XP reboot so I don't really want to be
4427 compatible! (tridge) */
4428 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4431 /* Check if this is an oplock break on a file
4432 we have granted an oplock on.
4434 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4435 /* Client can insist on breaking to none. */
4436 BOOL break_to_none = (oplocklevel == 0);
4438 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4439 (unsigned int)oplocklevel, fsp->fnum ));
4442 * Make sure we have granted an exclusive or batch oplock on this file.
4445 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4446 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4447 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4449 /* if this is a pure oplock break request then don't send a reply */
4450 if (num_locks == 0 && num_ulocks == 0) {
4451 END_PROFILE(SMBlockingX);
4454 END_PROFILE(SMBlockingX);
4455 return ERROR_DOS(ERRDOS,ERRlock);
4459 if (remove_oplock(fsp, break_to_none) == False) {
4460 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4464 /* if this is a pure oplock break request then don't send a reply */
4465 if (num_locks == 0 && num_ulocks == 0) {
4466 /* Sanity check - ensure a pure oplock break is not a
4468 if(CVAL(inbuf,smb_vwv0) != 0xff)
4469 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4470 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4471 END_PROFILE(SMBlockingX);
4477 * We do this check *after* we have checked this is not a oplock break
4478 * response message. JRA.
4481 release_level_2_oplocks_on_change(fsp);
4483 /* Data now points at the beginning of the list
4484 of smb_unlkrng structs */
4485 for(i = 0; i < (int)num_ulocks; i++) {
4486 lock_pid = get_lock_pid( data, i, large_file_format);
4487 count = get_lock_count( data, i, large_file_format);
4488 offset = get_lock_offset( data, i, large_file_format, &err);
4491 * There is no error code marked "stupid client bug".... :-).
4494 END_PROFILE(SMBlockingX);
4495 return ERROR_DOS(ERRDOS,ERRnoaccess);
4498 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4499 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4501 status = do_unlock(fsp,conn,lock_pid,count,offset);
4502 if (NT_STATUS_V(status)) {
4503 END_PROFILE(SMBlockingX);
4504 return ERROR_NT(status);
4508 /* Setup the timeout in seconds. */
4510 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4512 /* Now do any requested locks */
4513 data += ((large_file_format ? 20 : 10)*num_ulocks);
4515 /* Data now points at the beginning of the list
4516 of smb_lkrng structs */
4518 for(i = 0; i < (int)num_locks; i++) {
4519 lock_pid = get_lock_pid( data, i, large_file_format);
4520 count = get_lock_count( data, i, large_file_format);
4521 offset = get_lock_offset( data, i, large_file_format, &err);
4524 * There is no error code marked "stupid client bug".... :-).
4527 END_PROFILE(SMBlockingX);
4528 return ERROR_DOS(ERRDOS,ERRnoaccess);
4531 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4532 (double)offset, (double)count, (unsigned int)lock_pid,
4533 fsp->fsp_name, (int)lock_timeout ));
4535 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4536 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4537 if (NT_STATUS_V(status)) {
4539 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4540 * Even if it's our own lock context, we need to wait here as
4541 * there may be an unlock on the way.
4542 * So I removed a "&& !my_lock_ctx" from the following
4543 * if statement. JRA.
4545 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4547 * A blocking lock was requested. Package up
4548 * this smb into a queued request and push it
4549 * onto the blocking lock queue.
4551 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4552 END_PROFILE(SMBlockingX);
4560 /* If any of the above locks failed, then we must unlock
4561 all of the previous locks (X/Open spec). */
4562 if (i != num_locks && num_locks != 0) {
4564 * Ensure we don't do a remove on the lock that just failed,
4565 * as under POSIX rules, if we have a lock already there, we
4566 * will delete it (and we shouldn't) .....
4568 for(i--; i >= 0; i--) {
4569 lock_pid = get_lock_pid( data, i, large_file_format);
4570 count = get_lock_count( data, i, large_file_format);
4571 offset = get_lock_offset( data, i, large_file_format, &err);
4574 * There is no error code marked "stupid client bug".... :-).
4577 END_PROFILE(SMBlockingX);
4578 return ERROR_DOS(ERRDOS,ERRnoaccess);
4581 do_unlock(fsp,conn,lock_pid,count,offset);
4583 END_PROFILE(SMBlockingX);
4584 return ERROR_NT(status);
4587 set_message(outbuf,2,0,True);
4589 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4590 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4592 END_PROFILE(SMBlockingX);
4593 return chain_reply(inbuf,outbuf,length,bufsize);
4596 /****************************************************************************
4597 Reply to a SMBreadbmpx (read block multiplex) request.
4598 ****************************************************************************/
4600 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4611 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4612 START_PROFILE(SMBreadBmpx);
4614 /* this function doesn't seem to work - disable by default */
4615 if (!lp_readbmpx()) {
4616 END_PROFILE(SMBreadBmpx);
4617 return ERROR_DOS(ERRSRV,ERRuseSTD);
4620 outsize = set_message(outbuf,8,0,True);
4622 CHECK_FSP(fsp,conn);
4625 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4626 maxcount = SVAL(inbuf,smb_vwv3);
4628 data = smb_buf(outbuf);
4629 pad = ((long)data)%4;
4634 max_per_packet = bufsize-(outsize+pad);
4638 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4639 END_PROFILE(SMBreadBmpx);
4640 return ERROR_DOS(ERRDOS,ERRlock);
4644 size_t N = MIN(max_per_packet,tcount-total_read);
4646 nread = read_file(fsp,data,startpos,N);
4651 if (nread < (ssize_t)N)
4652 tcount = total_read + nread;
4654 set_message(outbuf,8,nread,False);
4655 SIVAL(outbuf,smb_vwv0,startpos);
4656 SSVAL(outbuf,smb_vwv2,tcount);
4657 SSVAL(outbuf,smb_vwv6,nread);
4658 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4660 if (!send_smb(smbd_server_fd(),outbuf))
4661 exit_server("reply_readbmpx: send_smb failed.");
4663 total_read += nread;
4665 } while (total_read < (ssize_t)tcount);
4667 END_PROFILE(SMBreadBmpx);
4671 /****************************************************************************
4672 Reply to a SMBsetattrE.
4673 ****************************************************************************/
4675 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4677 struct utimbuf unix_times;
4679 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4680 START_PROFILE(SMBsetattrE);
4682 outsize = set_message(outbuf,0,0,True);
4684 if(!fsp || (fsp->conn != conn)) {
4685 END_PROFILE(SMBgetattrE);
4686 return ERROR_DOS(ERRDOS,ERRbadfid);
4690 * Convert the DOS times into unix times. Ignore create
4691 * time as UNIX can't set this.
4694 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4695 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4698 * Patch from Ray Frush <frush@engr.colostate.edu>
4699 * Sometimes times are sent as zero - ignore them.
4702 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4703 /* Ignore request */
4704 if( DEBUGLVL( 3 ) ) {
4705 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4706 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4708 END_PROFILE(SMBsetattrE);
4710 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4711 /* set modify time = to access time if modify time was 0 */
4712 unix_times.modtime = unix_times.actime;
4715 /* Set the date on this file */
4716 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4717 END_PROFILE(SMBsetattrE);
4718 return ERROR_DOS(ERRDOS,ERRnoaccess);
4721 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4722 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4724 END_PROFILE(SMBsetattrE);
4729 /* Back from the dead for OS/2..... JRA. */
4731 /****************************************************************************
4732 Reply to a SMBwritebmpx (write block multiplex primary) request.
4733 ****************************************************************************/
4735 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4738 ssize_t nwritten = -1;
4745 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4746 START_PROFILE(SMBwriteBmpx);
4748 CHECK_FSP(fsp,conn);
4752 tcount = SVAL(inbuf,smb_vwv1);
4753 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4754 write_through = BITSETW(inbuf+smb_vwv7,0);
4755 numtowrite = SVAL(inbuf,smb_vwv10);
4756 smb_doff = SVAL(inbuf,smb_vwv11);
4758 data = smb_base(inbuf) + smb_doff;
4760 /* If this fails we need to send an SMBwriteC response,
4761 not an SMBwritebmpx - set this up now so we don't forget */
4762 SCVAL(outbuf,smb_com,SMBwritec);
4764 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4765 END_PROFILE(SMBwriteBmpx);
4766 return(ERROR_DOS(ERRDOS,ERRlock));
4769 nwritten = write_file(fsp,data,startpos,numtowrite);
4771 if(lp_syncalways(SNUM(conn)) || write_through)
4772 sync_file(conn,fsp);
4774 if(nwritten < (ssize_t)numtowrite) {
4775 END_PROFILE(SMBwriteBmpx);
4776 return(UNIXERROR(ERRHRD,ERRdiskfull));
4779 /* If the maximum to be written to this file
4780 is greater than what we just wrote then set
4781 up a secondary struct to be attached to this
4782 fd, we will use this to cache error messages etc. */
4784 if((ssize_t)tcount > nwritten) {
4785 write_bmpx_struct *wbms;
4786 if(fsp->wbmpx_ptr != NULL)
4787 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4789 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4791 DEBUG(0,("Out of memory in reply_readmpx\n"));
4792 END_PROFILE(SMBwriteBmpx);
4793 return(ERROR_DOS(ERRSRV,ERRnoresource));
4795 wbms->wr_mode = write_through;
4796 wbms->wr_discard = False; /* No errors yet */
4797 wbms->wr_total_written = nwritten;
4798 wbms->wr_errclass = 0;
4800 fsp->wbmpx_ptr = wbms;
4803 /* We are returning successfully, set the message type back to
4805 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4807 outsize = set_message(outbuf,1,0,True);
4809 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4811 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4812 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4814 if (write_through && tcount==nwritten) {
4815 /* We need to send both a primary and a secondary response */
4816 smb_setlen(outbuf,outsize - 4);
4817 if (!send_smb(smbd_server_fd(),outbuf))
4818 exit_server("reply_writebmpx: send_smb failed.");
4820 /* Now the secondary */
4821 outsize = set_message(outbuf,1,0,True);
4822 SCVAL(outbuf,smb_com,SMBwritec);
4823 SSVAL(outbuf,smb_vwv0,nwritten);
4826 END_PROFILE(SMBwriteBmpx);
4830 /****************************************************************************
4831 Reply to a SMBwritebs (write block multiplex secondary) request.
4832 ****************************************************************************/
4834 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4837 ssize_t nwritten = -1;
4844 write_bmpx_struct *wbms;
4845 BOOL send_response = False;
4846 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4847 START_PROFILE(SMBwriteBs);
4849 CHECK_FSP(fsp,conn);
4852 tcount = SVAL(inbuf,smb_vwv1);
4853 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4854 numtowrite = SVAL(inbuf,smb_vwv6);
4855 smb_doff = SVAL(inbuf,smb_vwv7);
4857 data = smb_base(inbuf) + smb_doff;
4859 /* We need to send an SMBwriteC response, not an SMBwritebs */
4860 SCVAL(outbuf,smb_com,SMBwritec);
4862 /* This fd should have an auxiliary struct attached,
4863 check that it does */
4864 wbms = fsp->wbmpx_ptr;
4866 END_PROFILE(SMBwriteBs);
4870 /* If write through is set we can return errors, else we must cache them */
4871 write_through = wbms->wr_mode;
4873 /* Check for an earlier error */
4874 if(wbms->wr_discard) {
4875 END_PROFILE(SMBwriteBs);
4876 return -1; /* Just discard the packet */
4879 nwritten = write_file(fsp,data,startpos,numtowrite);
4881 if(lp_syncalways(SNUM(conn)) || write_through)
4882 sync_file(conn,fsp);
4884 if (nwritten < (ssize_t)numtowrite) {
4886 /* We are returning an error - we can delete the aux struct */
4889 fsp->wbmpx_ptr = NULL;
4890 END_PROFILE(SMBwriteBs);
4891 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4893 END_PROFILE(SMBwriteBs);
4894 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4897 /* Increment the total written, if this matches tcount
4898 we can discard the auxiliary struct (hurrah !) and return a writeC */
4899 wbms->wr_total_written += nwritten;
4900 if(wbms->wr_total_written >= tcount) {
4901 if (write_through) {
4902 outsize = set_message(outbuf,1,0,True);
4903 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4904 send_response = True;
4908 fsp->wbmpx_ptr = NULL;
4912 END_PROFILE(SMBwriteBs);
4916 END_PROFILE(SMBwriteBs);
4920 /****************************************************************************
4921 Reply to a SMBgetattrE.
4922 ****************************************************************************/
4924 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4926 SMB_STRUCT_STAT sbuf;
4929 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4930 START_PROFILE(SMBgetattrE);
4932 outsize = set_message(outbuf,11,0,True);
4934 if(!fsp || (fsp->conn != conn)) {
4935 END_PROFILE(SMBgetattrE);
4936 return ERROR_DOS(ERRDOS,ERRbadfid);
4939 /* Do an fstat on this file */
4940 if(fsp_stat(fsp, &sbuf)) {
4941 END_PROFILE(SMBgetattrE);
4942 return(UNIXERROR(ERRDOS,ERRnoaccess));
4945 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4948 * Convert the times into dos times. Set create
4949 * date to be last modify date as UNIX doesn't save
4953 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4954 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4955 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4958 SIVAL(outbuf,smb_vwv6,0);
4959 SIVAL(outbuf,smb_vwv8,0);
4961 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4962 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4963 SIVAL(outbuf,smb_vwv8,allocation_size);
4965 SSVAL(outbuf,smb_vwv10, mode);
4967 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4969 END_PROFILE(SMBgetattrE);