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 BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern int global_oplock_break;
38 unsigned int smb_echo_count = 0;
40 extern BOOL global_encrypted_passwords_negotiated;
42 /****************************************************************************
43 Ensure we check the path in *exactly* the same way as W2K.
44 We're assuming here that '/' is not the second byte in any multibyte char
45 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
47 ****************************************************************************/
49 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
52 const char *s = srcname;
53 NTSTATUS ret = NT_STATUS_OK;
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
64 if ((s[0] == '.') && (s[1] == '\0')) {
65 ret = NT_STATUS_OBJECT_NAME_INVALID;
68 if ((d != destname) && (*s != '\0')) {
69 /* We only care about non-leading or trailing '/' or '\\' */
72 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
73 /* Uh oh - "../" or "..\\" or "..\0" ! */
76 * No mb char starts with '.' so we're safe checking the directory separator here.
79 /* If we just added a '/', delete it. */
81 if ((d > destname) && (*(d-1) == '/')) {
83 if (d == (destname + 1)) {
89 /* Are we at the start ? Can't go back further if so. */
91 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
94 /* Go back one level... */
95 /* We know this is safe as '/' cannot be part of a mb sequence. */
96 /* NOTE - if this assumption is invalid we are not in good shape... */
97 while (d > destname) {
103 } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || s[2] == '\0')) {
106 * No mb char starts with '.' so we're safe checking the directory separator here.
109 /* "./" or ".\\" fails with a different error depending on where it is... */
112 ret = NT_STATUS_OBJECT_NAME_INVALID;
115 if (s[1] != '\0' && s[2] == '\0') {
116 ret = NT_STATUS_INVALID_PARAMETER;
119 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
127 switch(next_mb_char_size(s)) {
138 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
140 return NT_STATUS_INVALID_PARAMETER;
149 /****************************************************************************
150 Pull a string and check the path - provide for error return.
151 ****************************************************************************/
153 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
156 char *tmppath_ptr = tmppath;
159 SMB_ASSERT(dest_len == sizeof(pstring));
163 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
165 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
167 *err = check_path_syntax(dest, tmppath);
171 /****************************************************************************
172 Reply to a special message.
173 ****************************************************************************/
175 int reply_special(char *inbuf,char *outbuf)
178 int msg_type = CVAL(inbuf,0);
179 int msg_flags = CVAL(inbuf,1);
183 static BOOL already_got_session = False;
187 memset(outbuf,'\0',smb_size);
189 smb_setlen(outbuf,0);
192 case 0x81: /* session request */
194 if (already_got_session) {
195 exit_server("multiple session request not permitted");
198 SCVAL(outbuf,0,0x82);
200 if (name_len(inbuf+4) > 50 ||
201 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
202 DEBUG(0,("Invalid name length in session request\n"));
205 name_extract(inbuf,4,name1);
206 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
207 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
210 set_local_machine_name(name1, True);
211 set_remote_machine_name(name2, True);
213 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
214 get_local_machine_name(), get_remote_machine_name(),
217 if (name_type == 'R') {
218 /* We are being asked for a pathworks session ---
220 SCVAL(outbuf, 0,0x83);
224 /* only add the client's machine name to the list
225 of possibly valid usernames if we are operating
226 in share mode security */
227 if (lp_security() == SEC_SHARE) {
228 add_session_user(get_remote_machine_name());
231 reload_services(True);
234 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
236 already_got_session = True;
239 case 0x89: /* session keepalive request
240 (some old clients produce this?) */
241 SCVAL(outbuf,0,SMBkeepalive);
245 case 0x82: /* positive session response */
246 case 0x83: /* negative session response */
247 case 0x84: /* retarget session response */
248 DEBUG(0,("Unexpected session response\n"));
251 case SMBkeepalive: /* session keepalive */
256 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
257 msg_type, msg_flags));
262 /****************************************************************************
264 ****************************************************************************/
266 int reply_tcon(connection_struct *conn,
267 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
274 uint16 vuid = SVAL(inbuf,smb_uid);
278 DATA_BLOB password_blob;
280 START_PROFILE(SMBtcon);
282 *service_buf = *password = *dev = 0;
284 p = smb_buf(inbuf)+1;
285 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
286 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
288 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
290 p = strrchr_m(service_buf,'\\');
294 service = service_buf;
297 password_blob = data_blob(password, pwlen+1);
299 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
301 data_blob_clear_free(&password_blob);
304 END_PROFILE(SMBtcon);
305 return ERROR_NT(nt_status);
308 outsize = set_message(outbuf,2,0,True);
309 SSVAL(outbuf,smb_vwv0,max_recv);
310 SSVAL(outbuf,smb_vwv1,conn->cnum);
311 SSVAL(outbuf,smb_tid,conn->cnum);
313 DEBUG(3,("tcon service=%s cnum=%d\n",
314 service, conn->cnum));
316 END_PROFILE(SMBtcon);
320 /****************************************************************************
321 Reply to a tcon and X.
322 ****************************************************************************/
324 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
329 /* what the cleint thinks the device is */
330 fstring client_devicetype;
331 /* what the server tells the client the share represents */
332 const char *server_devicetype;
334 uint16 vuid = SVAL(inbuf,smb_uid);
335 int passlen = SVAL(inbuf,smb_vwv3);
338 extern BOOL global_encrypted_passwords_negotiated;
340 START_PROFILE(SMBtconX);
342 *service = *client_devicetype = 0;
344 /* we might have to close an old one */
345 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
346 close_cnum(conn,vuid);
349 if (passlen > MAX_PASS_LEN) {
350 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
353 if (global_encrypted_passwords_negotiated) {
354 password = data_blob(smb_buf(inbuf),passlen);
356 password = data_blob(smb_buf(inbuf),passlen+1);
357 /* Ensure correct termination */
358 password.data[passlen]=0;
361 p = smb_buf(inbuf) + passlen;
362 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
365 * the service name can be either: \\server\share
366 * or share directly like on the DELL PowerVault 705
369 q = strchr_m(path+2,'\\');
371 END_PROFILE(SMBtconX);
372 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
374 fstrcpy(service,q+1);
377 fstrcpy(service,path);
379 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
381 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
383 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
385 data_blob_clear_free(&password);
388 END_PROFILE(SMBtconX);
389 return ERROR_NT(nt_status);
393 server_devicetype = "IPC";
394 else if ( IS_PRINT(conn) )
395 server_devicetype = "LPT1:";
397 server_devicetype = "A:";
399 if (Protocol < PROTOCOL_NT1) {
400 set_message(outbuf,2,0,True);
402 p += srvstr_push(outbuf, p, server_devicetype, -1,
403 STR_TERMINATE|STR_ASCII);
404 set_message_end(outbuf,p);
406 /* NT sets the fstype of IPC$ to the null string */
407 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
409 set_message(outbuf,3,0,True);
412 p += srvstr_push(outbuf, p, server_devicetype, -1,
413 STR_TERMINATE|STR_ASCII);
414 p += srvstr_push(outbuf, p, fstype, -1,
417 set_message_end(outbuf,p);
419 /* what does setting this bit do? It is set by NT4 and
420 may affect the ability to autorun mounted cdroms */
421 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
422 (lp_csc_policy(SNUM(conn)) << 2));
424 init_dfsroot(conn, inbuf, outbuf);
428 DEBUG(3,("tconX service=%s \n",
431 /* set the incoming and outgoing tid to the just created one */
432 SSVAL(inbuf,smb_tid,conn->cnum);
433 SSVAL(outbuf,smb_tid,conn->cnum);
435 END_PROFILE(SMBtconX);
436 return chain_reply(inbuf,outbuf,length,bufsize);
439 /****************************************************************************
440 Reply to an unknown type.
441 ****************************************************************************/
443 int reply_unknown(char *inbuf,char *outbuf)
446 type = CVAL(inbuf,smb_com);
448 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
449 smb_fn_name(type), type, type));
451 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
454 /****************************************************************************
456 ****************************************************************************/
458 int reply_ioctl(connection_struct *conn,
459 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
461 uint16 device = SVAL(inbuf,smb_vwv1);
462 uint16 function = SVAL(inbuf,smb_vwv2);
463 uint32 ioctl_code = (device << 16) + function;
464 int replysize, outsize;
466 START_PROFILE(SMBioctl);
468 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
470 switch (ioctl_code) {
471 case IOCTL_QUERY_JOB_INFO:
475 END_PROFILE(SMBioctl);
476 return(ERROR_DOS(ERRSRV,ERRnosupport));
479 outsize = set_message(outbuf,8,replysize+1,True);
480 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
481 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
482 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
483 p = smb_buf(outbuf) + 1; /* Allow for alignment */
485 switch (ioctl_code) {
486 case IOCTL_QUERY_JOB_INFO:
488 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
490 END_PROFILE(SMBioctl);
491 return(UNIXERROR(ERRDOS,ERRbadfid));
493 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
494 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
495 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
500 END_PROFILE(SMBioctl);
504 /****************************************************************************
506 ****************************************************************************/
508 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
514 BOOL bad_path = False;
515 SMB_STRUCT_STAT sbuf;
518 START_PROFILE(SMBchkpth);
520 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
521 if (!NT_STATUS_IS_OK(status)) {
522 END_PROFILE(SMBchkpth);
523 return ERROR_NT(status);
526 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
528 unix_convert(name,conn,0,&bad_path,&sbuf);
530 mode = SVAL(inbuf,smb_vwv0);
532 if (check_name(name,conn)) {
533 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
534 if (!(ok = S_ISDIR(sbuf.st_mode))) {
535 END_PROFILE(SMBchkpth);
536 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
541 /* We special case this - as when a Windows machine
542 is parsing a path is steps through the components
543 one at a time - if a component fails it expects
544 ERRbadpath, not ERRbadfile.
546 if(errno == ENOENT) {
548 * Windows returns different error codes if
549 * the parent directory is valid but not the
550 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
551 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
552 * if the path is invalid.
555 END_PROFILE(SMBchkpth);
556 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
558 END_PROFILE(SMBchkpth);
559 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
561 } else if (errno == ENOTDIR) {
562 END_PROFILE(SMBchkpth);
563 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
566 END_PROFILE(SMBchkpth);
567 return(UNIXERROR(ERRDOS,ERRbadpath));
570 outsize = set_message(outbuf,0,0,True);
572 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
574 END_PROFILE(SMBchkpth);
578 /****************************************************************************
580 ****************************************************************************/
582 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
586 SMB_STRUCT_STAT sbuf;
591 BOOL bad_path = False;
595 START_PROFILE(SMBgetatr);
597 p = smb_buf(inbuf) + 1;
598 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
599 if (!NT_STATUS_IS_OK(status)) {
600 END_PROFILE(SMBgetatr);
601 return ERROR_NT(status);
604 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
606 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
607 under WfWg - weird! */
609 mode = aHIDDEN | aDIR;
610 if (!CAN_WRITE(conn))
616 unix_convert(fname,conn,0,&bad_path,&sbuf);
617 if (check_name(fname,conn)) {
618 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
619 mode = dos_mode(conn,fname,&sbuf);
621 mtime = sbuf.st_mtime;
626 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
632 END_PROFILE(SMBgetatr);
633 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
636 outsize = set_message(outbuf,10,0,True);
638 SSVAL(outbuf,smb_vwv0,mode);
639 if(lp_dos_filetime_resolution(SNUM(conn)) )
640 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
642 put_dos_date3(outbuf,smb_vwv1,mtime);
643 SIVAL(outbuf,smb_vwv3,(uint32)size);
645 if (Protocol >= PROTOCOL_NT1)
646 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
648 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
650 END_PROFILE(SMBgetatr);
654 /****************************************************************************
656 ****************************************************************************/
658 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
665 SMB_STRUCT_STAT sbuf;
666 BOOL bad_path = False;
670 START_PROFILE(SMBsetatr);
672 p = smb_buf(inbuf) + 1;
673 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
674 if (!NT_STATUS_IS_OK(status)) {
675 END_PROFILE(SMBsetatr);
676 return ERROR_NT(status);
679 unix_convert(fname,conn,0,&bad_path,&sbuf);
681 mode = SVAL(inbuf,smb_vwv0);
682 mtime = make_unix_date3(inbuf+smb_vwv1);
684 if (mode != FILE_ATTRIBUTE_NORMAL) {
685 if (VALID_STAT_OF_DIR(sbuf))
690 if (check_name(fname,conn)) {
691 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
698 ok = set_filetime(conn,fname,mtime);
701 END_PROFILE(SMBsetatr);
702 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
705 outsize = set_message(outbuf,0,0,True);
707 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
709 END_PROFILE(SMBsetatr);
713 /****************************************************************************
715 ****************************************************************************/
717 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
720 SMB_BIG_UINT dfree,dsize,bsize;
721 START_PROFILE(SMBdskattr);
723 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
725 outsize = set_message(outbuf,5,0,True);
727 if (Protocol <= PROTOCOL_LANMAN2) {
728 double total_space, free_space;
729 /* we need to scale this to a number that DOS6 can handle. We
730 use floating point so we can handle large drives on systems
731 that don't have 64 bit integers
733 we end up displaying a maximum of 2G to DOS systems
735 total_space = dsize * (double)bsize;
736 free_space = dfree * (double)bsize;
738 dsize = (total_space+63*512) / (64*512);
739 dfree = (free_space+63*512) / (64*512);
741 if (dsize > 0xFFFF) dsize = 0xFFFF;
742 if (dfree > 0xFFFF) dfree = 0xFFFF;
744 SSVAL(outbuf,smb_vwv0,dsize);
745 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
746 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
747 SSVAL(outbuf,smb_vwv3,dfree);
749 SSVAL(outbuf,smb_vwv0,dsize);
750 SSVAL(outbuf,smb_vwv1,bsize/512);
751 SSVAL(outbuf,smb_vwv2,512);
752 SSVAL(outbuf,smb_vwv3,dfree);
755 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
757 END_PROFILE(SMBdskattr);
761 /****************************************************************************
763 Can be called from SMBsearch, SMBffirst or SMBfunique.
764 ****************************************************************************/
766 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
776 unsigned int numentries = 0;
777 unsigned int maxentries = 0;
778 BOOL finished = False;
785 BOOL check_descend = False;
786 BOOL expect_close = False;
787 BOOL can_open = True;
788 BOOL bad_path = False;
790 START_PROFILE(SMBsearch);
792 *mask = *directory = *fname = 0;
794 /* If we were called as SMBffirst then we must expect close. */
795 if(CVAL(inbuf,smb_com) == SMBffirst)
798 outsize = set_message(outbuf,1,3,True);
799 maxentries = SVAL(inbuf,smb_vwv0);
800 dirtype = SVAL(inbuf,smb_vwv1);
801 p = smb_buf(inbuf) + 1;
802 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
803 if (!NT_STATUS_IS_OK(nt_status)) {
804 END_PROFILE(SMBsearch);
805 return ERROR_NT(nt_status);
808 status_len = SVAL(p, 0);
811 /* dirtype &= ~aDIR; */
813 if (status_len == 0) {
814 SMB_STRUCT_STAT sbuf;
817 pstrcpy(directory,path);
819 unix_convert(directory,conn,0,&bad_path,&sbuf);
822 if (!check_name(directory,conn))
825 p = strrchr_m(dir2,'/');
834 p = strrchr_m(directory,'/');
840 if (strlen(directory) == 0)
841 pstrcpy(directory,".");
842 memset((char *)status,'\0',21);
843 SCVAL(status,0,(dirtype & 0x1F));
848 status_dirtype = CVAL(status,0) & 0x1F;
849 if (status_dirtype != (dirtype & 0x1F))
850 dirtype = status_dirtype;
852 conn->dirptr = dptr_fetch(status+12,&dptr_num);
855 string_set(&conn->dirpath,dptr_path(dptr_num));
856 pstrcpy(mask, dptr_wcard(dptr_num));
860 p = smb_buf(outbuf) + 3;
863 if (status_len == 0) {
864 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
867 END_PROFILE(SMBsearch);
868 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
870 END_PROFILE(SMBsearch);
871 return ERROR_DOS(ERRDOS,ERRnofids);
873 dptr_set_wcard(dptr_num, strdup(mask));
874 dptr_set_attr(dptr_num, dirtype);
876 dirtype = dptr_attr(dptr_num);
879 DEBUG(4,("dptr_num is %d\n",dptr_num));
882 if ((dirtype&0x1F) == aVOLID) {
884 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
885 dptr_fill(p+12,dptr_num);
886 if (dptr_zero(p+12) && (status_len==0))
890 p += DIR_STRUCT_SIZE;
893 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
895 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
896 conn->dirpath,lp_dontdescend(SNUM(conn))));
897 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
898 check_descend = True;
900 for (i=numentries;(i<maxentries) && !finished;i++) {
901 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
904 make_dir_struct(p,mask,fname,size,mode,date);
905 dptr_fill(p+12,dptr_num);
908 p += DIR_STRUCT_SIZE;
917 /* If we were called as SMBffirst with smb_search_id == NULL
918 and no entries were found then return error and close dirptr
921 if(ok && expect_close && numentries == 0 && status_len == 0) {
922 if (Protocol < PROTOCOL_NT1) {
923 SCVAL(outbuf,smb_rcls,ERRDOS);
924 SSVAL(outbuf,smb_err,ERRnofiles);
926 /* Also close the dptr - we know it's gone */
927 dptr_close(&dptr_num);
928 } else if (numentries == 0 || !ok) {
929 if (Protocol < PROTOCOL_NT1) {
930 SCVAL(outbuf,smb_rcls,ERRDOS);
931 SSVAL(outbuf,smb_err,ERRnofiles);
933 dptr_close(&dptr_num);
936 /* If we were called as SMBfunique, then we can close the dirptr now ! */
937 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
938 dptr_close(&dptr_num);
940 SSVAL(outbuf,smb_vwv0,numentries);
941 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
942 SCVAL(smb_buf(outbuf),0,5);
943 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
945 if (Protocol >= PROTOCOL_NT1)
946 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
948 outsize += DIR_STRUCT_SIZE*numentries;
949 smb_setlen(outbuf,outsize - 4);
951 if ((! *directory) && dptr_path(dptr_num))
952 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
954 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
955 smb_fn_name(CVAL(inbuf,smb_com)),
956 mask, directory, dirtype, numentries, maxentries ) );
958 END_PROFILE(SMBsearch);
962 /****************************************************************************
963 Reply to a fclose (stop directory search).
964 ****************************************************************************/
966 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
976 START_PROFILE(SMBfclose);
978 outsize = set_message(outbuf,1,0,True);
979 p = smb_buf(inbuf) + 1;
980 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
981 if (!NT_STATUS_IS_OK(err)) {
982 END_PROFILE(SMBfclose);
983 return ERROR_NT(err);
986 status_len = SVAL(p,0);
989 if (status_len == 0) {
990 END_PROFILE(SMBfclose);
991 return ERROR_DOS(ERRSRV,ERRsrverror);
996 if(dptr_fetch(status+12,&dptr_num)) {
997 /* Close the dptr - we know it's gone */
998 dptr_close(&dptr_num);
1001 SSVAL(outbuf,smb_vwv0,0);
1003 DEBUG(3,("search close\n"));
1005 END_PROFILE(SMBfclose);
1009 /****************************************************************************
1011 ****************************************************************************/
1013 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1022 SMB_STRUCT_STAT sbuf;
1023 BOOL bad_path = False;
1025 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1026 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1028 START_PROFILE(SMBopen);
1030 share_mode = SVAL(inbuf,smb_vwv0);
1032 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1033 if (!NT_STATUS_IS_OK(status)) {
1034 END_PROFILE(SMBopen);
1035 return ERROR_NT(status);
1038 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1040 unix_convert(fname,conn,0,&bad_path,&sbuf);
1042 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1043 (uint32)dos_attr, oplock_request,&rmode,NULL);
1046 END_PROFILE(SMBopen);
1047 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1050 size = sbuf.st_size;
1051 fmode = dos_mode(conn,fname,&sbuf);
1052 mtime = sbuf.st_mtime;
1055 DEBUG(3,("attempt to open a directory %s\n",fname));
1056 close_file(fsp,False);
1057 END_PROFILE(SMBopen);
1058 return ERROR_DOS(ERRDOS,ERRnoaccess);
1061 outsize = set_message(outbuf,7,0,True);
1062 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1063 SSVAL(outbuf,smb_vwv1,fmode);
1064 if(lp_dos_filetime_resolution(SNUM(conn)) )
1065 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1067 put_dos_date3(outbuf,smb_vwv2,mtime);
1068 SIVAL(outbuf,smb_vwv4,(uint32)size);
1069 SSVAL(outbuf,smb_vwv6,rmode);
1071 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1072 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1074 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1075 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1076 END_PROFILE(SMBopen);
1080 /****************************************************************************
1081 Reply to an open and X.
1082 ****************************************************************************/
1084 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1087 int smb_mode = SVAL(inbuf,smb_vwv3);
1088 int smb_attr = SVAL(inbuf,smb_vwv5);
1089 /* Breakout the oplock request bits so we can set the
1090 reply bits separately. */
1091 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1092 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1093 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1095 int open_flags = SVAL(inbuf,smb_vwv2);
1096 int smb_sattr = SVAL(inbuf,smb_vwv4);
1097 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1099 int smb_ofun = SVAL(inbuf,smb_vwv8);
1101 int fmode=0,mtime=0,rmode=0;
1102 SMB_STRUCT_STAT sbuf;
1104 BOOL bad_path = False;
1107 START_PROFILE(SMBopenX);
1109 /* If it's an IPC, pass off the pipe handler. */
1111 if (lp_nt_pipe_support()) {
1112 END_PROFILE(SMBopenX);
1113 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1115 END_PROFILE(SMBopenX);
1116 return ERROR_DOS(ERRSRV,ERRaccess);
1120 /* XXXX we need to handle passed times, sattr and flags */
1121 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 END_PROFILE(SMBopenX);
1124 return ERROR_NT(status);
1127 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1129 unix_convert(fname,conn,0,&bad_path,&sbuf);
1131 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1132 oplock_request, &rmode,&smb_action);
1135 END_PROFILE(SMBopenX);
1136 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1139 size = sbuf.st_size;
1140 fmode = dos_mode(conn,fname,&sbuf);
1141 mtime = sbuf.st_mtime;
1143 close_file(fsp,False);
1144 END_PROFILE(SMBopenX);
1145 return ERROR_DOS(ERRDOS,ERRnoaccess);
1148 /* If the caller set the extended oplock request bit
1149 and we granted one (by whatever means) - set the
1150 correct bit for extended oplock reply.
1153 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1154 smb_action |= EXTENDED_OPLOCK_GRANTED;
1156 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1157 smb_action |= EXTENDED_OPLOCK_GRANTED;
1159 /* If the caller set the core oplock request bit
1160 and we granted one (by whatever means) - set the
1161 correct bit for core oplock reply.
1164 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1165 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1167 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1168 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1170 set_message(outbuf,15,0,True);
1171 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1172 SSVAL(outbuf,smb_vwv3,fmode);
1173 if(lp_dos_filetime_resolution(SNUM(conn)) )
1174 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1176 put_dos_date3(outbuf,smb_vwv4,mtime);
1177 SIVAL(outbuf,smb_vwv6,(uint32)size);
1178 SSVAL(outbuf,smb_vwv8,rmode);
1179 SSVAL(outbuf,smb_vwv11,smb_action);
1181 END_PROFILE(SMBopenX);
1182 return chain_reply(inbuf,outbuf,length,bufsize);
1185 /****************************************************************************
1186 Reply to a SMBulogoffX.
1187 ****************************************************************************/
1189 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1191 uint16 vuid = SVAL(inbuf,smb_uid);
1192 user_struct *vuser = get_valid_user_struct(vuid);
1193 START_PROFILE(SMBulogoffX);
1196 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1198 /* in user level security we are supposed to close any files
1199 open by this user */
1200 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1201 file_close_user(vuid);
1203 invalidate_vuid(vuid);
1205 set_message(outbuf,2,0,True);
1207 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1209 END_PROFILE(SMBulogoffX);
1210 return chain_reply(inbuf,outbuf,length,bufsize);
1213 /****************************************************************************
1214 Reply to a mknew or a create.
1215 ****************************************************************************/
1217 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1224 BOOL bad_path = False;
1226 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1227 SMB_STRUCT_STAT sbuf;
1229 START_PROFILE(SMBcreate);
1231 com = SVAL(inbuf,smb_com);
1233 createmode = SVAL(inbuf,smb_vwv0);
1234 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1235 if (!NT_STATUS_IS_OK(status)) {
1236 END_PROFILE(SMBcreate);
1237 return ERROR_NT(status);
1240 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1242 unix_convert(fname,conn,0,&bad_path,&sbuf);
1244 if (createmode & aVOLID)
1245 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1247 if(com == SMBmknew) {
1248 /* We should fail if file exists. */
1249 ofun = FILE_CREATE_IF_NOT_EXIST;
1251 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1252 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1255 /* Open file in dos compatibility share mode. */
1256 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1257 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1260 END_PROFILE(SMBcreate);
1261 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1264 outsize = set_message(outbuf,1,0,True);
1265 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1267 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1268 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1270 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1271 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1273 DEBUG( 2, ( "new file %s\n", fname ) );
1274 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1276 END_PROFILE(SMBcreate);
1280 /****************************************************************************
1281 Reply to a create temporary file.
1282 ****************************************************************************/
1284 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1289 BOOL bad_path = False;
1291 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1293 SMB_STRUCT_STAT sbuf;
1297 START_PROFILE(SMBctemp);
1299 createattr = SVAL(inbuf,smb_vwv0);
1300 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 END_PROFILE(SMBctemp);
1303 return ERROR_NT(status);
1305 pstrcat(fname,"\\TMXXXXXX");
1307 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1309 unix_convert(fname,conn,0,&bad_path,&sbuf);
1311 tmpfd = smb_mkstemp(fname);
1313 END_PROFILE(SMBctemp);
1314 return(UNIXERROR(ERRDOS,ERRnoaccess));
1317 SMB_VFS_STAT(conn,fname,&sbuf);
1319 /* Open file in dos compatibility share mode. */
1320 /* We should fail if file does not exist. */
1321 fsp = open_file_shared(conn,fname,&sbuf,
1322 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1323 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1324 (uint32)createattr, oplock_request, NULL, NULL);
1326 /* close fd from smb_mkstemp() */
1330 END_PROFILE(SMBctemp);
1331 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1334 outsize = set_message(outbuf,1,0,True);
1335 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1337 /* the returned filename is relative to the directory */
1338 s = strrchr_m(fname, '/');
1344 p = smb_buf(outbuf);
1345 SSVALS(p, 0, -1); /* what is this? not in spec */
1346 SSVAL(p, 2, strlen(s));
1348 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1349 outsize = set_message_end(outbuf, p);
1351 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1352 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1354 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1355 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1357 DEBUG( 2, ( "created temp file %s\n", fname ) );
1358 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1359 fname, fsp->fd, sbuf.st_mode ) );
1361 END_PROFILE(SMBctemp);
1365 /*******************************************************************
1366 Check if a user is allowed to rename a file.
1367 ********************************************************************/
1369 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1375 if (!CAN_WRITE(conn))
1376 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1378 if (S_ISDIR(pst->st_mode))
1379 return NT_STATUS_OK;
1381 /* We need a better way to return NT status codes from open... */
1385 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1386 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1389 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1390 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1391 ret = NT_STATUS_SHARING_VIOLATION;
1394 unix_ERR_ntstatus = NT_STATUS_OK;
1397 close_file(fsp,False);
1398 return NT_STATUS_OK;
1401 /*******************************************************************
1402 Check if a user is allowed to delete a file.
1403 ********************************************************************/
1405 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1407 SMB_STRUCT_STAT sbuf;
1413 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1416 if (!CAN_WRITE(conn))
1417 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1419 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1420 if(errno == ENOENT) {
1422 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1424 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1426 return map_nt_error_from_unix(errno);
1429 fmode = dos_mode(conn,fname,&sbuf);
1431 /* Can't delete a directory. */
1433 return NT_STATUS_FILE_IS_A_DIRECTORY;
1435 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1436 return NT_STATUS_OBJECT_NAME_INVALID;
1437 #endif /* JRATEST */
1439 if (!lp_delete_readonly(SNUM(conn))) {
1441 return NT_STATUS_CANNOT_DELETE;
1443 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1444 return NT_STATUS_NO_SUCH_FILE;
1446 /* We need a better way to return NT status codes from open... */
1450 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1451 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1454 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1455 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1456 ret = unix_ERR_ntstatus;
1457 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1458 ret = NT_STATUS_SHARING_VIOLATION;
1461 unix_ERR_ntstatus = NT_STATUS_OK;
1464 close_file(fsp,False);
1465 return NT_STATUS_OK;
1468 /****************************************************************************
1469 The guts of the unlink command, split out so it may be called by the NT SMB
1471 ****************************************************************************/
1473 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1479 NTSTATUS error = NT_STATUS_OK;
1481 BOOL bad_path = False;
1483 SMB_STRUCT_STAT sbuf;
1485 *directory = *mask = 0;
1487 /* We must check for wildcards in the name given
1488 * directly by the client - before any unmangling.
1489 * This prevents an unmangling of a UNIX name containing
1490 * a DOS wildcard like '*' or '?' from unmangling into
1491 * a wildcard delete which was not intended.
1492 * FIX for #226. JRA.
1495 has_wild = ms_has_wild(name);
1497 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1499 p = strrchr_m(name,'/');
1501 pstrcpy(directory,".");
1505 pstrcpy(directory,name);
1510 * We should only check the mangled cache
1511 * here if unix_convert failed. This means
1512 * that the path in 'mask' doesn't exist
1513 * on the file system and so we need to look
1514 * for a possible mangle. This patch from
1515 * Tine Smukavec <valentin.smukavec@hermes.si>.
1518 if (!rc && mangle_is_mangled(mask))
1519 mangle_check_cache( mask );
1522 pstrcat(directory,"/");
1523 pstrcat(directory,mask);
1524 error = can_delete(directory,conn,dirtype,bad_path);
1525 if (!NT_STATUS_IS_OK(error))
1528 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1532 void *dirptr = NULL;
1535 if (check_name(directory,conn))
1536 dirptr = OpenDir(conn, directory, True);
1538 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1539 the pattern matches against the long name, otherwise the short name
1540 We don't implement this yet XXXX
1544 error = NT_STATUS_NO_SUCH_FILE;
1546 if (strequal(mask,"????????.???"))
1549 while ((dname = ReadDirName(dirptr))) {
1551 BOOL sys_direntry = False;
1552 pstrcpy(fname,dname);
1554 /* Quick check for "." and ".." */
1555 if (fname[0] == '.') {
1556 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1557 if ((dirtype & aDIR)) {
1558 sys_direntry = True;
1565 if(!mask_match(fname, mask, case_sensitive))
1569 error = NT_STATUS_OBJECT_NAME_INVALID;
1573 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1574 error = can_delete(fname,conn,dirtype,bad_path);
1575 if (!NT_STATUS_IS_OK(error))
1577 if (SMB_VFS_UNLINK(conn,fname) == 0)
1579 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1585 if (count == 0 && NT_STATUS_IS_OK(error)) {
1586 error = map_nt_error_from_unix(errno);
1592 /****************************************************************************
1594 ****************************************************************************/
1596 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1603 START_PROFILE(SMBunlink);
1605 dirtype = SVAL(inbuf,smb_vwv0);
1607 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1608 if (!NT_STATUS_IS_OK(status)) {
1609 END_PROFILE(SMBunlink);
1610 return ERROR_NT(status);
1613 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1615 DEBUG(3,("reply_unlink : %s\n",name));
1617 status = unlink_internals(conn, dirtype, name);
1618 if (!NT_STATUS_IS_OK(status))
1619 return ERROR_NT(status);
1622 * Win2k needs a changenotify request response before it will
1623 * update after a rename..
1625 process_pending_change_notify_queue((time_t)0);
1627 outsize = set_message(outbuf,0,0,True);
1629 END_PROFILE(SMBunlink);
1633 /****************************************************************************
1635 ****************************************************************************/
1637 void fail_readraw(void)
1640 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1642 exit_server(errstr);
1645 /****************************************************************************
1646 Use sendfile in readbraw.
1647 ****************************************************************************/
1649 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1650 ssize_t mincount, char *outbuf)
1654 #if defined(WITH_SENDFILE)
1656 * We can only use sendfile on a non-chained packet and on a file
1657 * that is exclusively oplocked. reply_readbraw has already checked the length.
1660 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1661 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1664 _smb_setlen(outbuf,nread);
1665 header.data = outbuf;
1669 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1671 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1672 * return ENOSYS then pretend we just got a normal read.
1674 if (errno == ENOSYS)
1677 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1678 fsp->fsp_name, strerror(errno) ));
1679 exit_server("send_file_readbraw sendfile failed");
1688 ret = read_file(fsp,outbuf+4,startpos,nread);
1689 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1698 _smb_setlen(outbuf,ret);
1699 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1703 /****************************************************************************
1704 Reply to a readbraw (core+ protocol).
1705 ****************************************************************************/
1707 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1709 extern struct current_user current_user;
1710 ssize_t maxcount,mincount;
1713 char *header = outbuf;
1715 START_PROFILE(SMBreadbraw);
1717 if (srv_is_signing_active()) {
1718 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1722 * Special check if an oplock break has been issued
1723 * and the readraw request croses on the wire, we must
1724 * return a zero length response here.
1727 if(global_oplock_break) {
1728 _smb_setlen(header,0);
1729 if (write_data(smbd_server_fd(),header,4) != 4)
1731 DEBUG(5,("readbraw - oplock break finished\n"));
1732 END_PROFILE(SMBreadbraw);
1736 fsp = file_fsp(inbuf,smb_vwv0);
1738 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1740 * fsp could be NULL here so use the value from the packet. JRA.
1742 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1743 _smb_setlen(header,0);
1744 if (write_data(smbd_server_fd(),header,4) != 4)
1746 END_PROFILE(SMBreadbraw);
1750 CHECK_FSP(fsp,conn);
1752 flush_write_cache(fsp, READRAW_FLUSH);
1754 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1755 if(CVAL(inbuf,smb_wct) == 10) {
1757 * This is a large offset (64 bit) read.
1759 #ifdef LARGE_SMB_OFF_T
1761 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1763 #else /* !LARGE_SMB_OFF_T */
1766 * Ensure we haven't been sent a >32 bit offset.
1769 if(IVAL(inbuf,smb_vwv8) != 0) {
1770 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1771 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1772 _smb_setlen(header,0);
1773 if (write_data(smbd_server_fd(),header,4) != 4)
1775 END_PROFILE(SMBreadbraw);
1779 #endif /* LARGE_SMB_OFF_T */
1782 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1783 _smb_setlen(header,0);
1784 if (write_data(smbd_server_fd(),header,4) != 4)
1786 END_PROFILE(SMBreadbraw);
1790 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1791 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1793 /* ensure we don't overrun the packet size */
1794 maxcount = MIN(65535,maxcount);
1796 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1797 SMB_OFF_T size = fsp->size;
1798 SMB_OFF_T sizeneeded = startpos + maxcount;
1800 if (size < sizeneeded) {
1802 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1804 if (!fsp->can_write)
1808 if (startpos >= size)
1811 nread = MIN(maxcount,(size - startpos));
1814 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1815 if (nread < mincount)
1819 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1820 (int)maxcount, (int)mincount, (int)nread ) );
1822 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1824 DEBUG(5,("readbraw finished\n"));
1825 END_PROFILE(SMBreadbraw);
1829 /****************************************************************************
1830 Reply to a lockread (core+ protocol).
1831 ****************************************************************************/
1833 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1841 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1842 BOOL my_lock_ctx = False;
1843 START_PROFILE(SMBlockread);
1845 CHECK_FSP(fsp,conn);
1848 release_level_2_oplocks_on_change(fsp);
1850 numtoread = SVAL(inbuf,smb_vwv1);
1851 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1853 outsize = set_message(outbuf,5,3,True);
1854 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1855 data = smb_buf(outbuf) + 3;
1858 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1859 * protocol request that predates the read/write lock concept.
1860 * Thus instead of asking for a read lock here we need to ask
1861 * for a write lock. JRA.
1862 * Note that the requested lock size is unaffected by max_recv.
1865 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1866 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1868 if (NT_STATUS_V(status)) {
1871 * We used to make lockread a blocking lock. It turns out
1872 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1876 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1878 * A blocking lock was requested. Package up
1879 * this smb into a queued request and push it
1880 * onto the blocking lock queue.
1882 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1883 (SMB_BIG_UINT)numtoread)) {
1884 END_PROFILE(SMBlockread);
1889 END_PROFILE(SMBlockread);
1890 return ERROR_NT(status);
1894 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1897 if (numtoread > max_recv) {
1898 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1899 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1900 (unsigned int)numtoread, (unsigned int)max_recv ));
1901 numtoread = MIN(numtoread,max_recv);
1903 nread = read_file(fsp,data,startpos,numtoread);
1906 END_PROFILE(SMBlockread);
1907 return(UNIXERROR(ERRDOS,ERRnoaccess));
1911 SSVAL(outbuf,smb_vwv0,nread);
1912 SSVAL(outbuf,smb_vwv5,nread+3);
1913 SSVAL(smb_buf(outbuf),1,nread);
1915 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1916 fsp->fnum, (int)numtoread, (int)nread));
1918 END_PROFILE(SMBlockread);
1922 /****************************************************************************
1924 ****************************************************************************/
1926 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1933 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1934 START_PROFILE(SMBread);
1936 CHECK_FSP(fsp,conn);
1939 numtoread = SVAL(inbuf,smb_vwv1);
1940 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1942 outsize = set_message(outbuf,5,3,True);
1943 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1945 * The requested read size cannot be greater than max_recv. JRA.
1947 if (numtoread > max_recv) {
1948 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1949 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1950 (unsigned int)numtoread, (unsigned int)max_recv ));
1951 numtoread = MIN(numtoread,max_recv);
1954 data = smb_buf(outbuf) + 3;
1956 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1957 END_PROFILE(SMBread);
1958 return ERROR_DOS(ERRDOS,ERRlock);
1962 nread = read_file(fsp,data,startpos,numtoread);
1965 END_PROFILE(SMBread);
1966 return(UNIXERROR(ERRDOS,ERRnoaccess));
1970 SSVAL(outbuf,smb_vwv0,nread);
1971 SSVAL(outbuf,smb_vwv5,nread+3);
1972 SCVAL(smb_buf(outbuf),0,1);
1973 SSVAL(smb_buf(outbuf),1,nread);
1975 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1976 fsp->fnum, (int)numtoread, (int)nread ) );
1978 END_PROFILE(SMBread);
1982 /****************************************************************************
1983 Reply to a read and X - possibly using sendfile.
1984 ****************************************************************************/
1986 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1987 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1990 char *data = smb_buf(outbuf);
1992 #if defined(WITH_SENDFILE)
1994 * We can only use sendfile on a non-chained packet and on a file
1995 * that is exclusively oplocked.
1998 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1999 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2000 SMB_STRUCT_STAT sbuf;
2003 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2004 return(UNIXERROR(ERRDOS,ERRnoaccess));
2006 if (startpos > sbuf.st_size)
2009 if (smb_maxcnt > (sbuf.st_size - startpos))
2010 smb_maxcnt = (sbuf.st_size - startpos);
2012 if (smb_maxcnt == 0)
2016 * Set up the packet header before send. We
2017 * assume here the sendfile will work (get the
2018 * correct amount of data).
2021 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2022 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2023 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2024 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2025 SCVAL(outbuf,smb_vwv0,0xFF);
2026 set_message(outbuf,12,smb_maxcnt,False);
2027 header.data = outbuf;
2028 header.length = data - outbuf;
2031 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2033 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2034 * return ENOSYS then pretend we just got a normal read.
2036 if (errno == ENOSYS)
2039 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2040 fsp->fsp_name, strerror(errno) ));
2041 exit_server("send_file_readX sendfile failed");
2044 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2045 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2053 nread = read_file(fsp,data,startpos,smb_maxcnt);
2056 END_PROFILE(SMBreadX);
2057 return(UNIXERROR(ERRDOS,ERRnoaccess));
2060 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2061 SSVAL(outbuf,smb_vwv5,nread);
2062 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2063 SSVAL(smb_buf(outbuf),-2,nread);
2065 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2066 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2071 /****************************************************************************
2072 Reply to a read and X.
2073 ****************************************************************************/
2075 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2077 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2078 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2080 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2082 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2085 START_PROFILE(SMBreadX);
2087 /* If it's an IPC, pass off the pipe handler. */
2089 END_PROFILE(SMBreadX);
2090 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2093 CHECK_FSP(fsp,conn);
2096 set_message(outbuf,12,0,True);
2098 if(CVAL(inbuf,smb_wct) == 12) {
2099 #ifdef LARGE_SMB_OFF_T
2101 * This is a large offset (64 bit) read.
2103 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2105 #else /* !LARGE_SMB_OFF_T */
2108 * Ensure we haven't been sent a >32 bit offset.
2111 if(IVAL(inbuf,smb_vwv10) != 0) {
2112 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2113 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2114 END_PROFILE(SMBreadX);
2115 return ERROR_DOS(ERRDOS,ERRbadaccess);
2118 #endif /* LARGE_SMB_OFF_T */
2122 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2123 END_PROFILE(SMBreadX);
2124 return ERROR_DOS(ERRDOS,ERRlock);
2127 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2129 nread = chain_reply(inbuf,outbuf,length,bufsize);
2131 END_PROFILE(SMBreadX);
2135 /****************************************************************************
2136 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2137 ****************************************************************************/
2139 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2142 ssize_t total_written=0;
2143 size_t numtowrite=0;
2148 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2150 START_PROFILE(SMBwritebraw);
2152 if (srv_is_signing_active()) {
2153 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2156 CHECK_FSP(fsp,conn);
2159 tcount = IVAL(inbuf,smb_vwv1);
2160 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2161 write_through = BITSETW(inbuf+smb_vwv7,0);
2163 /* We have to deal with slightly different formats depending
2164 on whether we are using the core+ or lanman1.0 protocol */
2166 if(Protocol <= PROTOCOL_COREPLUS) {
2167 numtowrite = SVAL(smb_buf(inbuf),-2);
2168 data = smb_buf(inbuf);
2170 numtowrite = SVAL(inbuf,smb_vwv10);
2171 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2174 /* force the error type */
2175 SCVAL(inbuf,smb_com,SMBwritec);
2176 SCVAL(outbuf,smb_com,SMBwritec);
2178 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2179 END_PROFILE(SMBwritebraw);
2180 return(ERROR_DOS(ERRDOS,ERRlock));
2184 nwritten = write_file(fsp,data,startpos,numtowrite);
2186 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2187 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2189 if (nwritten < (ssize_t)numtowrite) {
2190 END_PROFILE(SMBwritebraw);
2191 return(UNIXERROR(ERRHRD,ERRdiskfull));
2194 total_written = nwritten;
2196 /* Return a message to the redirector to tell it to send more bytes */
2197 SCVAL(outbuf,smb_com,SMBwritebraw);
2198 SSVALS(outbuf,smb_vwv0,-1);
2199 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2200 if (!send_smb(smbd_server_fd(),outbuf))
2201 exit_server("reply_writebraw: send_smb failed.");
2203 /* Now read the raw data into the buffer and write it */
2204 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2205 exit_server("secondary writebraw failed");
2208 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2209 numtowrite = smb_len(inbuf);
2211 /* Set up outbuf to return the correct return */
2212 outsize = set_message(outbuf,1,0,True);
2213 SCVAL(outbuf,smb_com,SMBwritec);
2214 SSVAL(outbuf,smb_vwv0,total_written);
2216 if (numtowrite != 0) {
2218 if (numtowrite > BUFFER_SIZE) {
2219 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2220 (unsigned int)numtowrite ));
2221 exit_server("secondary writebraw failed");
2224 if (tcount > nwritten+numtowrite) {
2225 DEBUG(3,("Client overestimated the write %d %d %d\n",
2226 (int)tcount,(int)nwritten,(int)numtowrite));
2229 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2230 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2232 exit_server("secondary writebraw failed");
2235 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2237 if (nwritten < (ssize_t)numtowrite) {
2238 SCVAL(outbuf,smb_rcls,ERRHRD);
2239 SSVAL(outbuf,smb_err,ERRdiskfull);
2243 total_written += nwritten;
2246 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2247 sync_file(conn,fsp);
2249 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2250 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2252 /* we won't return a status if write through is not selected - this follows what WfWg does */
2253 END_PROFILE(SMBwritebraw);
2254 if (!write_through && total_written==tcount) {
2256 #if RABBIT_PELLET_FIX
2258 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2259 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2261 if (!send_keepalive(smbd_server_fd()))
2262 exit_server("reply_writebraw: send of keepalive failed");
2270 /****************************************************************************
2271 Reply to a writeunlock (core+).
2272 ****************************************************************************/
2274 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2275 int size, int dum_buffsize)
2277 ssize_t nwritten = -1;
2281 NTSTATUS status = NT_STATUS_OK;
2282 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2284 START_PROFILE(SMBwriteunlock);
2286 CHECK_FSP(fsp,conn);
2289 numtowrite = SVAL(inbuf,smb_vwv1);
2290 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2291 data = smb_buf(inbuf) + 3;
2293 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2294 WRITE_LOCK,False)) {
2295 END_PROFILE(SMBwriteunlock);
2296 return ERROR_DOS(ERRDOS,ERRlock);
2299 /* The special X/Open SMB protocol handling of
2300 zero length writes is *NOT* done for
2305 nwritten = write_file(fsp,data,startpos,numtowrite);
2307 if (lp_syncalways(SNUM(conn)))
2308 sync_file(conn,fsp);
2310 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2311 END_PROFILE(SMBwriteunlock);
2312 return(UNIXERROR(ERRHRD,ERRdiskfull));
2316 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2317 (SMB_BIG_UINT)startpos);
2318 if (NT_STATUS_V(status)) {
2319 END_PROFILE(SMBwriteunlock);
2320 return ERROR_NT(status);
2324 outsize = set_message(outbuf,1,0,True);
2326 SSVAL(outbuf,smb_vwv0,nwritten);
2328 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2329 fsp->fnum, (int)numtowrite, (int)nwritten));
2331 END_PROFILE(SMBwriteunlock);
2335 /****************************************************************************
2337 ****************************************************************************/
2339 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2342 ssize_t nwritten = -1;
2345 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2347 START_PROFILE(SMBwrite);
2349 /* If it's an IPC, pass off the pipe handler. */
2351 END_PROFILE(SMBwrite);
2352 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2355 CHECK_FSP(fsp,conn);
2358 numtowrite = SVAL(inbuf,smb_vwv1);
2359 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2360 data = smb_buf(inbuf) + 3;
2362 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2363 END_PROFILE(SMBwrite);
2364 return ERROR_DOS(ERRDOS,ERRlock);
2368 * X/Open SMB protocol says that if smb_vwv1 is
2369 * zero then the file size should be extended or
2370 * truncated to the size given in smb_vwv[2-3].
2373 if(numtowrite == 0) {
2375 * This is actually an allocate call, and set EOF. JRA.
2377 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2379 END_PROFILE(SMBwrite);
2380 return ERROR_NT(NT_STATUS_DISK_FULL);
2382 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2384 END_PROFILE(SMBwrite);
2385 return ERROR_NT(NT_STATUS_DISK_FULL);
2388 nwritten = write_file(fsp,data,startpos,numtowrite);
2390 if (lp_syncalways(SNUM(conn)))
2391 sync_file(conn,fsp);
2393 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2394 END_PROFILE(SMBwrite);
2395 return(UNIXERROR(ERRHRD,ERRdiskfull));
2398 outsize = set_message(outbuf,1,0,True);
2400 SSVAL(outbuf,smb_vwv0,nwritten);
2402 if (nwritten < (ssize_t)numtowrite) {
2403 SCVAL(outbuf,smb_rcls,ERRHRD);
2404 SSVAL(outbuf,smb_err,ERRdiskfull);
2407 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2409 END_PROFILE(SMBwrite);
2413 /****************************************************************************
2414 Reply to a write and X.
2415 ****************************************************************************/
2417 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2419 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2420 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2421 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2422 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2423 ssize_t nwritten = -1;
2424 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2425 unsigned int smblen = smb_len(inbuf);
2427 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2428 START_PROFILE(SMBwriteX);
2430 /* If it's an IPC, pass off the pipe handler. */
2432 END_PROFILE(SMBwriteX);
2433 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2436 CHECK_FSP(fsp,conn);
2439 /* Deal with possible LARGE_WRITEX */
2441 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2443 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2444 END_PROFILE(SMBwriteX);
2445 return ERROR_DOS(ERRDOS,ERRbadmem);
2448 data = smb_base(inbuf) + smb_doff;
2450 if(CVAL(inbuf,smb_wct) == 14) {
2451 #ifdef LARGE_SMB_OFF_T
2453 * This is a large offset (64 bit) write.
2455 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2457 #else /* !LARGE_SMB_OFF_T */
2460 * Ensure we haven't been sent a >32 bit offset.
2463 if(IVAL(inbuf,smb_vwv12) != 0) {
2464 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2465 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2466 END_PROFILE(SMBwriteX);
2467 return ERROR_DOS(ERRDOS,ERRbadaccess);
2470 #endif /* LARGE_SMB_OFF_T */
2473 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2474 END_PROFILE(SMBwriteX);
2475 return ERROR_DOS(ERRDOS,ERRlock);
2478 /* X/Open SMB protocol says that, unlike SMBwrite
2479 if the length is zero then NO truncation is
2480 done, just a write of zero. To truncate a file,
2486 nwritten = write_file(fsp,data,startpos,numtowrite);
2488 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2489 END_PROFILE(SMBwriteX);
2490 return(UNIXERROR(ERRHRD,ERRdiskfull));
2493 set_message(outbuf,6,0,True);
2495 SSVAL(outbuf,smb_vwv2,nwritten);
2497 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2499 if (nwritten < (ssize_t)numtowrite) {
2500 SCVAL(outbuf,smb_rcls,ERRHRD);
2501 SSVAL(outbuf,smb_err,ERRdiskfull);
2504 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2505 fsp->fnum, (int)numtowrite, (int)nwritten));
2507 if (lp_syncalways(SNUM(conn)) || write_through)
2508 sync_file(conn,fsp);
2510 END_PROFILE(SMBwriteX);
2511 return chain_reply(inbuf,outbuf,length,bufsize);
2514 /****************************************************************************
2516 ****************************************************************************/
2518 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2524 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2525 START_PROFILE(SMBlseek);
2527 CHECK_FSP(fsp,conn);
2529 flush_write_cache(fsp, SEEK_FLUSH);
2531 mode = SVAL(inbuf,smb_vwv1) & 3;
2532 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2533 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2542 res = fsp->pos + startpos;
2553 if (umode == SEEK_END) {
2554 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2555 if(errno == EINVAL) {
2556 SMB_OFF_T current_pos = startpos;
2557 SMB_STRUCT_STAT sbuf;
2559 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2560 END_PROFILE(SMBlseek);
2561 return(UNIXERROR(ERRDOS,ERRnoaccess));
2564 current_pos += sbuf.st_size;
2566 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2571 END_PROFILE(SMBlseek);
2572 return(UNIXERROR(ERRDOS,ERRnoaccess));
2578 outsize = set_message(outbuf,2,0,True);
2579 SIVAL(outbuf,smb_vwv0,res);
2581 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2582 fsp->fnum, (double)startpos, (double)res, mode));
2584 END_PROFILE(SMBlseek);
2588 /****************************************************************************
2590 ****************************************************************************/
2592 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2594 int outsize = set_message(outbuf,0,0,True);
2595 uint16 fnum = SVAL(inbuf,smb_vwv0);
2596 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2597 START_PROFILE(SMBflush);
2600 CHECK_FSP(fsp,conn);
2603 file_sync_all(conn);
2605 sync_file(conn,fsp);
2608 DEBUG(3,("flush\n"));
2609 END_PROFILE(SMBflush);
2613 /****************************************************************************
2615 ****************************************************************************/
2617 int reply_exit(connection_struct *conn,
2618 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2621 START_PROFILE(SMBexit);
2623 file_close_pid(SVAL(inbuf,smb_pid));
2625 outsize = set_message(outbuf,0,0,True);
2627 DEBUG(3,("exit\n"));
2629 END_PROFILE(SMBexit);
2633 /****************************************************************************
2634 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2635 ****************************************************************************/
2637 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2640 extern struct current_user current_user;
2643 int32 eclass = 0, err = 0;
2644 files_struct *fsp = NULL;
2645 START_PROFILE(SMBclose);
2647 outsize = set_message(outbuf,0,0,True);
2649 /* If it's an IPC, pass off to the pipe handler. */
2651 END_PROFILE(SMBclose);
2652 return reply_pipe_close(conn, inbuf,outbuf);
2655 fsp = file_fsp(inbuf,smb_vwv0);
2658 * We can only use CHECK_FSP if we know it's not a directory.
2661 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2662 END_PROFILE(SMBclose);
2663 return ERROR_DOS(ERRDOS,ERRbadfid);
2666 if(fsp->is_directory) {
2668 * Special case - close NT SMB directory handle.
2670 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2671 close_file(fsp,True);
2674 * Close ordinary file.
2679 /* Save the name for time set in close. */
2680 pstrcpy( file_name, fsp->fsp_name);
2682 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2684 conn->num_files_open));
2687 * close_file() returns the unix errno if an error
2688 * was detected on close - normally this is due to
2689 * a disk full error. If not then it was probably an I/O error.
2692 if((close_err = close_file(fsp,True)) != 0) {
2694 END_PROFILE(SMBclose);
2695 return (UNIXERROR(ERRHRD,ERRgeneral));
2699 * Now take care of any time sent in the close.
2702 mtime = make_unix_date3(inbuf+smb_vwv1);
2704 /* try and set the date */
2705 set_filetime(conn, file_name, mtime);
2709 /* We have a cached error */
2711 END_PROFILE(SMBclose);
2712 return ERROR_DOS(eclass,err);
2715 END_PROFILE(SMBclose);
2719 /****************************************************************************
2720 Reply to a writeclose (Core+ protocol).
2721 ****************************************************************************/
2723 int reply_writeclose(connection_struct *conn,
2724 char *inbuf,char *outbuf, int size, int dum_buffsize)
2727 ssize_t nwritten = -1;
2733 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2734 START_PROFILE(SMBwriteclose);
2736 CHECK_FSP(fsp,conn);
2739 numtowrite = SVAL(inbuf,smb_vwv1);
2740 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2741 mtime = make_unix_date3(inbuf+smb_vwv4);
2742 data = smb_buf(inbuf) + 1;
2744 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2745 END_PROFILE(SMBwriteclose);
2746 return ERROR_DOS(ERRDOS,ERRlock);
2749 nwritten = write_file(fsp,data,startpos,numtowrite);
2751 set_filetime(conn, fsp->fsp_name,mtime);
2754 * More insanity. W2K only closes the file if writelen > 0.
2759 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2761 close_err = close_file(fsp,True);
2764 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2765 fsp->fnum, (int)numtowrite, (int)nwritten,
2766 conn->num_files_open));
2768 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2769 END_PROFILE(SMBwriteclose);
2770 return(UNIXERROR(ERRHRD,ERRdiskfull));
2773 if(close_err != 0) {
2775 END_PROFILE(SMBwriteclose);
2776 return(UNIXERROR(ERRHRD,ERRgeneral));
2779 outsize = set_message(outbuf,1,0,True);
2781 SSVAL(outbuf,smb_vwv0,nwritten);
2782 END_PROFILE(SMBwriteclose);
2786 /****************************************************************************
2788 ****************************************************************************/
2790 int reply_lock(connection_struct *conn,
2791 char *inbuf,char *outbuf, int length, int dum_buffsize)
2793 int outsize = set_message(outbuf,0,0,True);
2794 SMB_BIG_UINT count,offset;
2796 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2797 BOOL my_lock_ctx = False;
2799 START_PROFILE(SMBlock);
2801 CHECK_FSP(fsp,conn);
2803 release_level_2_oplocks_on_change(fsp);
2805 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2806 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2808 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2809 fsp->fd, fsp->fnum, (double)offset, (double)count));
2811 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2812 if (NT_STATUS_V(status)) {
2814 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2815 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2817 * A blocking lock was requested. Package up
2818 * this smb into a queued request and push it
2819 * onto the blocking lock queue.
2821 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2822 END_PROFILE(SMBlock);
2827 END_PROFILE(SMBlock);
2828 return ERROR_NT(status);
2831 END_PROFILE(SMBlock);
2835 /****************************************************************************
2837 ****************************************************************************/
2839 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2842 int outsize = set_message(outbuf,0,0,True);
2843 SMB_BIG_UINT count,offset;
2845 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2846 START_PROFILE(SMBunlock);
2848 CHECK_FSP(fsp,conn);
2850 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2851 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2853 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2854 if (NT_STATUS_V(status)) {
2855 END_PROFILE(SMBunlock);
2856 return ERROR_NT(status);
2859 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2860 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2862 END_PROFILE(SMBunlock);
2866 /****************************************************************************
2868 ****************************************************************************/
2870 int reply_tdis(connection_struct *conn,
2871 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2873 int outsize = set_message(outbuf,0,0,True);
2875 START_PROFILE(SMBtdis);
2877 vuid = SVAL(inbuf,smb_uid);
2880 DEBUG(4,("Invalid connection in tdis\n"));
2881 END_PROFILE(SMBtdis);
2882 return ERROR_DOS(ERRSRV,ERRinvnid);
2887 close_cnum(conn,vuid);
2889 END_PROFILE(SMBtdis);
2893 /****************************************************************************
2895 ****************************************************************************/
2897 int reply_echo(connection_struct *conn,
2898 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2900 int smb_reverb = SVAL(inbuf,smb_vwv0);
2902 unsigned int data_len = smb_buflen(inbuf);
2903 int outsize = set_message(outbuf,1,data_len,True);
2904 START_PROFILE(SMBecho);
2906 if (data_len > BUFFER_SIZE) {
2907 DEBUG(0,("reply_echo: data_len too large.\n"));
2908 END_PROFILE(SMBecho);
2912 /* copy any incoming data back out */
2914 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2916 if (smb_reverb > 100) {
2917 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2921 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2922 SSVAL(outbuf,smb_vwv0,seq_num);
2924 smb_setlen(outbuf,outsize - 4);
2926 if (!send_smb(smbd_server_fd(),outbuf))
2927 exit_server("reply_echo: send_smb failed.");
2930 DEBUG(3,("echo %d times\n", smb_reverb));
2934 END_PROFILE(SMBecho);
2938 /****************************************************************************
2939 Reply to a printopen.
2940 ****************************************************************************/
2942 int reply_printopen(connection_struct *conn,
2943 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2947 START_PROFILE(SMBsplopen);
2949 if (!CAN_PRINT(conn)) {
2950 END_PROFILE(SMBsplopen);
2951 return ERROR_DOS(ERRDOS,ERRnoaccess);
2954 /* Open for exclusive use, write only. */
2955 fsp = print_fsp_open(conn, NULL);
2958 END_PROFILE(SMBsplopen);
2959 return(UNIXERROR(ERRDOS,ERRnoaccess));
2962 outsize = set_message(outbuf,1,0,True);
2963 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2965 DEBUG(3,("openprint fd=%d fnum=%d\n",
2966 fsp->fd, fsp->fnum));
2968 END_PROFILE(SMBsplopen);
2972 /****************************************************************************
2973 Reply to a printclose.
2974 ****************************************************************************/
2976 int reply_printclose(connection_struct *conn,
2977 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2979 int outsize = set_message(outbuf,0,0,True);
2980 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2982 START_PROFILE(SMBsplclose);
2984 CHECK_FSP(fsp,conn);
2986 if (!CAN_PRINT(conn)) {
2987 END_PROFILE(SMBsplclose);
2988 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2991 DEBUG(3,("printclose fd=%d fnum=%d\n",
2992 fsp->fd,fsp->fnum));
2994 close_err = close_file(fsp,True);
2996 if(close_err != 0) {
2998 END_PROFILE(SMBsplclose);
2999 return(UNIXERROR(ERRHRD,ERRgeneral));
3002 END_PROFILE(SMBsplclose);
3006 /****************************************************************************
3007 Reply to a printqueue.
3008 ****************************************************************************/
3010 int reply_printqueue(connection_struct *conn,
3011 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3013 int outsize = set_message(outbuf,2,3,True);
3014 int max_count = SVAL(inbuf,smb_vwv0);
3015 int start_index = SVAL(inbuf,smb_vwv1);
3016 START_PROFILE(SMBsplretq);
3018 /* we used to allow the client to get the cnum wrong, but that
3019 is really quite gross and only worked when there was only
3020 one printer - I think we should now only accept it if they
3021 get it right (tridge) */
3022 if (!CAN_PRINT(conn)) {
3023 END_PROFILE(SMBsplretq);
3024 return ERROR_DOS(ERRDOS,ERRnoaccess);
3027 SSVAL(outbuf,smb_vwv0,0);
3028 SSVAL(outbuf,smb_vwv1,0);
3029 SCVAL(smb_buf(outbuf),0,1);
3030 SSVAL(smb_buf(outbuf),1,0);
3032 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3033 start_index, max_count));
3036 print_queue_struct *queue = NULL;
3037 print_status_struct status;
3038 char *p = smb_buf(outbuf) + 3;
3039 int count = print_queue_status(SNUM(conn), &queue, &status);
3040 int num_to_get = ABS(max_count);
3041 int first = (max_count>0?start_index:start_index+max_count+1);
3047 num_to_get = MIN(num_to_get,count-first);
3050 for (i=first;i<first+num_to_get;i++) {
3051 put_dos_date2(p,0,queue[i].time);
3052 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3053 SSVAL(p,5, queue[i].job);
3054 SIVAL(p,7,queue[i].size);
3056 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3061 outsize = set_message(outbuf,2,28*count+3,False);
3062 SSVAL(outbuf,smb_vwv0,count);
3063 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3064 SCVAL(smb_buf(outbuf),0,1);
3065 SSVAL(smb_buf(outbuf),1,28*count);
3070 DEBUG(3,("%d entries returned in queue\n",count));
3073 END_PROFILE(SMBsplretq);
3077 /****************************************************************************
3078 Reply to a printwrite.
3079 ****************************************************************************/
3081 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3084 int outsize = set_message(outbuf,0,0,True);
3086 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3088 START_PROFILE(SMBsplwr);
3090 if (!CAN_PRINT(conn)) {
3091 END_PROFILE(SMBsplwr);
3092 return ERROR_DOS(ERRDOS,ERRnoaccess);
3095 CHECK_FSP(fsp,conn);
3098 numtowrite = SVAL(smb_buf(inbuf),1);
3099 data = smb_buf(inbuf) + 3;
3101 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3102 END_PROFILE(SMBsplwr);
3103 return(UNIXERROR(ERRHRD,ERRdiskfull));
3106 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3108 END_PROFILE(SMBsplwr);
3112 /****************************************************************************
3113 The guts of the mkdir command, split out so it may be called by the NT SMB
3115 ****************************************************************************/
3117 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3119 BOOL bad_path = False;
3120 SMB_STRUCT_STAT sbuf;
3123 unix_convert(directory,conn,0,&bad_path,&sbuf);
3125 if( strchr_m(directory, ':')) {
3126 return NT_STATUS_NOT_A_DIRECTORY;
3129 if (ms_has_wild(directory)) {
3130 return NT_STATUS_OBJECT_NAME_INVALID;
3133 if (check_name(directory, conn))
3134 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3137 if(errno == ENOENT) {
3139 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3141 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3143 return map_nt_error_from_unix(errno);
3146 return NT_STATUS_OK;
3149 /****************************************************************************
3151 ****************************************************************************/
3153 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3158 START_PROFILE(SMBmkdir);
3160 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3161 if (!NT_STATUS_IS_OK(status)) {
3162 END_PROFILE(SMBmkdir);
3163 return ERROR_NT(status);
3166 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3168 status = mkdir_internal(conn, directory);
3169 if (!NT_STATUS_IS_OK(status)) {
3170 END_PROFILE(SMBmkdir);
3171 return ERROR_NT(status);
3174 outsize = set_message(outbuf,0,0,True);
3176 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3178 END_PROFILE(SMBmkdir);
3182 /****************************************************************************
3183 Static function used by reply_rmdir to delete an entire directory
3184 tree recursively. Return False on ok, True on fail.
3185 ****************************************************************************/
3187 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3189 const char *dname = NULL;
3191 void *dirptr = OpenDir(conn, directory, False);
3196 while((dname = ReadDirName(dirptr))) {
3200 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3203 /* Construct the full name. */
3204 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3210 pstrcpy(fullname, directory);
3211 pstrcat(fullname, "/");
3212 pstrcat(fullname, dname);
3214 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3219 if(st.st_mode & S_IFDIR) {
3220 if(recursive_rmdir(conn, fullname)!=0) {
3224 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3228 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3237 /****************************************************************************
3238 The internals of the rmdir code - called elsewhere.
3239 ****************************************************************************/
3241 BOOL rmdir_internals(connection_struct *conn, char *directory)
3245 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3246 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3248 * Check to see if the only thing in this directory are
3249 * vetoed files/directories. If so then delete them and
3250 * retry. If we fail to delete any of them (and we *don't*
3251 * do a recursive delete) then fail the rmdir.
3253 BOOL all_veto_files = True;
3255 void *dirptr = OpenDir(conn, directory, False);
3257 if(dirptr != NULL) {
3258 int dirpos = TellDir(dirptr);
3259 while ((dname = ReadDirName(dirptr))) {
3260 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3262 if(!IS_VETO_PATH(conn, dname)) {
3263 all_veto_files = False;
3268 if(all_veto_files) {
3269 SeekDir(dirptr,dirpos);
3270 while ((dname = ReadDirName(dirptr))) {
3274 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3277 /* Construct the full name. */
3278 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3283 pstrcpy(fullname, directory);
3284 pstrcat(fullname, "/");
3285 pstrcat(fullname, dname);
3287 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3289 if(st.st_mode & S_IFDIR) {
3290 if(lp_recursive_veto_delete(SNUM(conn))) {
3291 if(recursive_rmdir(conn, fullname) != 0)
3294 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3296 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3300 /* Retry the rmdir */
3301 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3311 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3316 /****************************************************************************
3318 ****************************************************************************/
3320 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3325 BOOL bad_path = False;
3326 SMB_STRUCT_STAT sbuf;
3328 START_PROFILE(SMBrmdir);
3330 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3331 if (!NT_STATUS_IS_OK(status)) {
3332 END_PROFILE(SMBrmdir);
3333 return ERROR_NT(status);
3336 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3338 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3340 if (check_name(directory,conn)) {
3341 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3342 ok = rmdir_internals(conn, directory);
3346 END_PROFILE(SMBrmdir);
3347 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3350 outsize = set_message(outbuf,0,0,True);
3352 DEBUG( 3, ( "rmdir %s\n", directory ) );
3354 END_PROFILE(SMBrmdir);
3358 /*******************************************************************
3359 Resolve wildcards in a filename rename.
3360 Note that name is in UNIX charset and thus potentially can be more
3361 than fstring buffer (255 bytes) especially in default UTF-8 case.
3362 Therefore, we use pstring inside and all calls should ensure that
3363 name2 is at least pstring-long (they do already)
3364 ********************************************************************/
3366 static BOOL resolve_wildcards(const char *name1, char *name2)
3368 pstring root1,root2;
3370 char *p,*p2, *pname1, *pname2;
3371 int available_space, actual_space;
3374 pname1 = strrchr_m(name1,'/');
3375 pname2 = strrchr_m(name2,'/');
3377 if (!pname1 || !pname2)
3380 pstrcpy(root1,pname1);
3381 pstrcpy(root2,pname2);
3382 p = strrchr_m(root1,'.');
3389 p = strrchr_m(root2,'.');
3423 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3426 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3427 if (actual_space >= available_space - 1) {
3428 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3429 actual_space - available_space));
3432 pstrcpy_base(pname2, root2, name2);
3438 /****************************************************************************
3439 Ensure open files have their names updates.
3440 ****************************************************************************/
3442 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3445 BOOL did_rename = False;
3447 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3448 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3449 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3450 fsp->fsp_name, newname ));
3451 string_set(&fsp->fsp_name, newname);
3456 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3457 (unsigned int)dev, (double)inode, newname ));
3460 /****************************************************************************
3461 Rename an open file - given an fsp.
3462 ****************************************************************************/
3464 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3466 SMB_STRUCT_STAT sbuf;
3467 BOOL bad_path = False;
3468 pstring newname_last_component;
3469 NTSTATUS error = NT_STATUS_OK;
3474 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3476 /* Quick check for "." and ".." */
3477 if (!bad_path && newname_last_component[0] == '.') {
3478 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3479 return NT_STATUS_ACCESS_DENIED;
3482 if (!rcdest && bad_path) {
3483 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3486 /* Ensure newname contains a '/' */
3487 if(strrchr_m(newname,'/') == 0) {
3490 pstrcpy(tmpstr, "./");
3491 pstrcat(tmpstr, newname);
3492 pstrcpy(newname, tmpstr);
3496 * Check for special case with case preserving and not
3497 * case sensitive. If the old last component differs from the original
3498 * last component only by case, then we should allow
3499 * the rename (user is trying to change the case of the
3503 if((case_sensitive == False) && (case_preserve == True) &&
3504 strequal(newname, fsp->fsp_name)) {
3506 pstring newname_modified_last_component;
3509 * Get the last component of the modified name.
3510 * Note that we guarantee that newname contains a '/'
3513 p = strrchr_m(newname,'/');
3514 pstrcpy(newname_modified_last_component,p+1);
3516 if(strcsequal(newname_modified_last_component,
3517 newname_last_component) == False) {
3519 * Replace the modified last component with
3522 pstrcpy(p+1, newname_last_component);
3527 * If the src and dest names are identical - including case,
3528 * don't do the rename, just return success.
3531 if (strcsequal(fsp->fsp_name, newname)) {
3532 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3534 return NT_STATUS_OK;
3537 dest_exists = vfs_object_exist(conn,newname,NULL);
3539 if(!replace_if_exists && dest_exists) {
3540 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3541 fsp->fsp_name,newname));
3542 return NT_STATUS_OBJECT_NAME_COLLISION;
3545 error = can_rename(newname,conn,&sbuf);
3547 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3548 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3549 nt_errstr(error), fsp->fsp_name,newname));
3550 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3551 error = NT_STATUS_ACCESS_DENIED;
3555 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3556 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3557 fsp->fsp_name,newname));
3558 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3559 return NT_STATUS_OK;
3562 if (errno == ENOTDIR || errno == EISDIR)
3563 error = NT_STATUS_OBJECT_NAME_COLLISION;
3565 error = map_nt_error_from_unix(errno);
3567 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3568 nt_errstr(error), fsp->fsp_name,newname));
3573 /****************************************************************************
3574 The guts of the rename command, split out so it may be called by the NT SMB
3576 ****************************************************************************/
3578 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3582 pstring last_component_src;
3583 pstring last_component_dest;
3586 BOOL bad_path_src = False;
3587 BOOL bad_path_dest = False;
3589 NTSTATUS error = NT_STATUS_OK;
3592 SMB_STRUCT_STAT sbuf1, sbuf2;
3594 *directory = *mask = 0;
3599 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3600 if (!rc && bad_path_src) {
3601 if (ms_has_wild(last_component_src))
3602 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3603 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3606 /* Quick check for "." and ".." */
3607 if (last_component_src[0] == '.') {
3608 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3609 return NT_STATUS_OBJECT_NAME_INVALID;
3613 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3615 /* Quick check for "." and ".." */
3616 if (last_component_dest[0] == '.') {
3617 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3618 return NT_STATUS_OBJECT_NAME_INVALID;
3623 * Split the old name into directory and last component
3624 * strings. Note that unix_convert may have stripped off a
3625 * leading ./ from both name and newname if the rename is
3626 * at the root of the share. We need to make sure either both
3627 * name and newname contain a / character or neither of them do
3628 * as this is checked in resolve_wildcards().
3631 p = strrchr_m(name,'/');
3633 pstrcpy(directory,".");
3637 pstrcpy(directory,name);
3639 *p = '/'; /* Replace needed for exceptional test below. */
3643 * We should only check the mangled cache
3644 * here if unix_convert failed. This means
3645 * that the path in 'mask' doesn't exist
3646 * on the file system and so we need to look
3647 * for a possible mangle. This patch from
3648 * Tine Smukavec <valentin.smukavec@hermes.si>.
3651 if (!rc && mangle_is_mangled(mask))
3652 mangle_check_cache( mask );
3654 has_wild = ms_has_wild(mask);
3658 * No wildcards - just process the one file.
3660 BOOL is_short_name = mangle_is_8_3(name, True);
3662 /* Add a terminating '/' to the directory name. */
3663 pstrcat(directory,"/");
3664 pstrcat(directory,mask);
3666 /* Ensure newname contains a '/' also */
3667 if(strrchr_m(newname,'/') == 0) {
3670 pstrcpy(tmpstr, "./");
3671 pstrcat(tmpstr, newname);
3672 pstrcpy(newname, tmpstr);
3675 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3676 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3677 case_sensitive, case_preserve, short_case_preserve, directory,
3678 newname, last_component_dest, is_short_name));
3681 * Check for special case with case preserving and not
3682 * case sensitive, if directory and newname are identical,
3683 * and the old last component differs from the original
3684 * last component only by case, then we should allow
3685 * the rename (user is trying to change the case of the
3688 if((case_sensitive == False) &&
3689 (((case_preserve == True) &&
3690 (is_short_name == False)) ||
3691 ((short_case_preserve == True) &&
3692 (is_short_name == True))) &&
3693 strcsequal(directory, newname)) {
3694 pstring modified_last_component;
3697 * Get the last component of the modified name.
3698 * Note that we guarantee that newname contains a '/'
3701 p = strrchr_m(newname,'/');
3702 pstrcpy(modified_last_component,p+1);
3704 if(strcsequal(modified_last_component,
3705 last_component_dest) == False) {
3707 * Replace the modified last component with
3710 pstrcpy(p+1, last_component_dest);
3714 resolve_wildcards(directory,newname);
3717 * The source object must exist.
3720 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3721 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3722 directory,newname));
3724 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3726 * Must return different errors depending on whether the parent
3727 * directory existed or not.
3730 p = strrchr_m(directory, '/');
3732 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3734 if (vfs_object_exist(conn, directory, NULL))
3735 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3736 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3738 error = map_nt_error_from_unix(errno);
3739 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3740 nt_errstr(error), directory,newname));
3745 if (!rcdest && bad_path_dest) {
3746 if (ms_has_wild(last_component_dest))
3747 return NT_STATUS_OBJECT_NAME_INVALID;
3748 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3751 error = can_rename(directory,conn,&sbuf1);
3753 if (!NT_STATUS_IS_OK(error)) {
3754 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3755 nt_errstr(error), directory,newname));
3760 * If the src and dest names are identical - including case,
3761 * don't do the rename, just return success.
3764 if (strcsequal(directory, newname)) {
3765 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3766 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3767 return NT_STATUS_OK;
3770 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3771 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3772 directory,newname));
3773 return NT_STATUS_OBJECT_NAME_COLLISION;
3776 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3777 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3778 directory,newname));
3779 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3780 return NT_STATUS_OK;
3783 if (errno == ENOTDIR || errno == EISDIR)
3784 error = NT_STATUS_OBJECT_NAME_COLLISION;
3786 error = map_nt_error_from_unix(errno);
3788 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3789 nt_errstr(error), directory,newname));
3794 * Wildcards - process each file that matches.
3796 void *dirptr = NULL;
3800 if (check_name(directory,conn))
3801 dirptr = OpenDir(conn, directory, True);
3804 error = NT_STATUS_NO_SUCH_FILE;
3805 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3807 if (strequal(mask,"????????.???"))
3810 while ((dname = ReadDirName(dirptr))) {
3812 BOOL sysdir_entry = False;
3814 pstrcpy(fname,dname);
3816 /* Quick check for "." and ".." */
3817 if (fname[0] == '.') {
3818 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3820 sysdir_entry = True;
3827 if(!mask_match(fname, mask, case_sensitive))
3831 error = NT_STATUS_OBJECT_NAME_INVALID;
3835 error = NT_STATUS_ACCESS_DENIED;
3836 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3837 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3838 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3839 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3842 error = can_rename(fname,conn,&sbuf1);
3843 if (!NT_STATUS_IS_OK(error)) {
3844 DEBUG(6,("rename %s refused\n", fname));
3847 pstrcpy(destname,newname);
3849 if (!resolve_wildcards(fname,destname)) {
3850 DEBUG(6,("resolve_wildcards %s %s failed\n",
3855 if (!replace_if_exists &&
3856 vfs_file_exist(conn,destname, NULL)) {
3857 DEBUG(6,("file_exist %s\n", destname));
3858 error = NT_STATUS_OBJECT_NAME_COLLISION;
3862 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3863 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3865 error = NT_STATUS_OK;
3867 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3872 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3873 if (!rcdest && bad_path_dest) {
3874 if (ms_has_wild(last_component_dest))
3875 return NT_STATUS_OBJECT_NAME_INVALID;
3876 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3881 if (count == 0 && NT_STATUS_IS_OK(error)) {
3882 error = map_nt_error_from_unix(errno);
3888 /****************************************************************************
3890 ****************************************************************************/
3892 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3899 uint16 attrs = SVAL(inbuf,smb_vwv0);
3902 START_PROFILE(SMBmv);
3904 p = smb_buf(inbuf) + 1;
3905 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3906 if (!NT_STATUS_IS_OK(status)) {
3908 return ERROR_NT(status);
3911 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3912 if (!NT_STATUS_IS_OK(status)) {
3914 return ERROR_NT(status);
3917 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3918 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3920 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3922 status = rename_internals(conn, name, newname, attrs, False);
3923 if (!NT_STATUS_IS_OK(status)) {
3925 return ERROR_NT(status);
3929 * Win2k needs a changenotify request response before it will
3930 * update after a rename..
3932 process_pending_change_notify_queue((time_t)0);
3933 outsize = set_message(outbuf,0,0,True);
3939 /*******************************************************************
3940 Copy a file as part of a reply_copy.
3941 ******************************************************************/
3943 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3944 int count,BOOL target_is_directory, int *err_ret)
3947 SMB_STRUCT_STAT src_sbuf, sbuf2;
3949 files_struct *fsp1,*fsp2;
3955 pstrcpy(dest,dest1);
3956 if (target_is_directory) {
3957 char *p = strrchr_m(src,'/');
3966 if (!vfs_file_exist(conn,src,&src_sbuf))
3969 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3970 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
3975 if (!target_is_directory && count)
3976 ofun = FILE_EXISTS_OPEN;
3978 dosattrs = dos_mode(conn, src, &src_sbuf);
3979 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3980 ZERO_STRUCTP(&sbuf2);
3982 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3983 ofun,dosattrs,0,&Access,&action);
3986 close_file(fsp1,False);
3990 if ((ofun&3) == 1) {
3991 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3992 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3994 * Stop the copy from occurring.
3997 src_sbuf.st_size = 0;
4001 if (src_sbuf.st_size)
4002 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4004 close_file(fsp1,False);
4006 /* Ensure the modtime is set correctly on the destination file. */
4007 fsp2->pending_modtime = src_sbuf.st_mtime;
4010 * As we are opening fsp1 read-only we only expect
4011 * an error on close on fsp2 if we are out of space.
4012 * Thus we don't look at the error return from the
4015 *err_ret = close_file(fsp2,False);
4017 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4020 /****************************************************************************
4021 Reply to a file copy.
4022 ****************************************************************************/
4024 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4029 pstring mask,newname;
4032 int error = ERRnoaccess;
4036 int tid2 = SVAL(inbuf,smb_vwv0);
4037 int ofun = SVAL(inbuf,smb_vwv1);
4038 int flags = SVAL(inbuf,smb_vwv2);
4039 BOOL target_is_directory=False;
4040 BOOL bad_path1 = False;
4041 BOOL bad_path2 = False;
4043 SMB_STRUCT_STAT sbuf1, sbuf2;
4046 START_PROFILE(SMBcopy);
4048 *directory = *mask = 0;
4051 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4052 if (!NT_STATUS_IS_OK(status)) {
4053 END_PROFILE(SMBcopy);
4054 return ERROR_NT(status);
4056 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 END_PROFILE(SMBcopy);
4059 return ERROR_NT(status);
4062 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4064 if (tid2 != conn->cnum) {
4065 /* can't currently handle inter share copies XXXX */
4066 DEBUG(3,("Rejecting inter-share copy\n"));
4067 END_PROFILE(SMBcopy);
4068 return ERROR_DOS(ERRSRV,ERRinvdevice);
4071 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4072 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4074 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4075 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4077 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4079 if ((flags&1) && target_is_directory) {
4080 END_PROFILE(SMBcopy);
4081 return ERROR_DOS(ERRDOS,ERRbadfile);
4084 if ((flags&2) && !target_is_directory) {
4085 END_PROFILE(SMBcopy);
4086 return ERROR_DOS(ERRDOS,ERRbadpath);
4089 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4090 /* wants a tree copy! XXXX */
4091 DEBUG(3,("Rejecting tree copy\n"));
4092 END_PROFILE(SMBcopy);
4093 return ERROR_DOS(ERRSRV,ERRerror);
4096 p = strrchr_m(name,'/');
4098 pstrcpy(directory,"./");
4102 pstrcpy(directory,name);
4107 * We should only check the mangled cache
4108 * here if unix_convert failed. This means
4109 * that the path in 'mask' doesn't exist
4110 * on the file system and so we need to look
4111 * for a possible mangle. This patch from
4112 * Tine Smukavec <valentin.smukavec@hermes.si>.
4115 if (!rc && mangle_is_mangled(mask))
4116 mangle_check_cache( mask );
4118 has_wild = ms_has_wild(mask);
4121 pstrcat(directory,"/");
4122 pstrcat(directory,mask);
4123 if (resolve_wildcards(directory,newname) &&
4124 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4128 END_PROFILE(SMBcopy);
4129 return(UNIXERROR(ERRHRD,ERRgeneral));
4132 exists = vfs_file_exist(conn,directory,NULL);
4135 void *dirptr = NULL;
4139 if (check_name(directory,conn))
4140 dirptr = OpenDir(conn, directory, True);
4145 if (strequal(mask,"????????.???"))
4148 while ((dname = ReadDirName(dirptr))) {
4150 pstrcpy(fname,dname);
4152 if(!mask_match(fname, mask, case_sensitive))
4155 error = ERRnoaccess;
4156 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4157 pstrcpy(destname,newname);
4158 if (resolve_wildcards(fname,destname) &&
4159 copy_file(fname,destname,conn,ofun,
4160 count,target_is_directory,&err))
4162 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4170 /* Error on close... */
4172 END_PROFILE(SMBcopy);
4173 return(UNIXERROR(ERRHRD,ERRgeneral));
4177 END_PROFILE(SMBcopy);
4178 return ERROR_DOS(ERRDOS,error);
4180 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4181 unix_ERR_class = ERRDOS;
4182 unix_ERR_code = ERRbadpath;
4184 END_PROFILE(SMBcopy);
4185 return(UNIXERROR(ERRDOS,error));
4189 outsize = set_message(outbuf,1,0,True);
4190 SSVAL(outbuf,smb_vwv0,count);
4192 END_PROFILE(SMBcopy);
4196 /****************************************************************************
4198 ****************************************************************************/
4200 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4208 START_PROFILE(pathworks_setdir);
4211 if (!CAN_SETDIR(snum)) {
4212 END_PROFILE(pathworks_setdir);
4213 return ERROR_DOS(ERRDOS,ERRnoaccess);
4216 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4217 if (!NT_STATUS_IS_OK(status)) {
4218 END_PROFILE(pathworks_setdir);
4219 return ERROR_NT(status);
4222 if (strlen(newdir) == 0) {
4225 ok = vfs_directory_exist(conn,newdir,NULL);
4227 string_set(&conn->connectpath,newdir);
4231 END_PROFILE(pathworks_setdir);
4232 return ERROR_DOS(ERRDOS,ERRbadpath);
4235 outsize = set_message(outbuf,0,0,True);
4236 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4238 DEBUG(3,("setdir %s\n", newdir));
4240 END_PROFILE(pathworks_setdir);
4244 /****************************************************************************
4245 Get a lock pid, dealing with large count requests.
4246 ****************************************************************************/
4248 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4250 if(!large_file_format)
4251 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4253 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4256 /****************************************************************************
4257 Get a lock count, dealing with large count requests.
4258 ****************************************************************************/
4260 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4262 SMB_BIG_UINT count = 0;
4264 if(!large_file_format) {
4265 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4268 #if defined(HAVE_LONGLONG)
4269 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4270 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4271 #else /* HAVE_LONGLONG */
4274 * NT4.x seems to be broken in that it sends large file (64 bit)
4275 * lockingX calls even if the CAP_LARGE_FILES was *not*
4276 * negotiated. For boxes without large unsigned ints truncate the
4277 * lock count by dropping the top 32 bits.
4280 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4281 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4282 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4283 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4284 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4287 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4288 #endif /* HAVE_LONGLONG */
4294 #if !defined(HAVE_LONGLONG)
4295 /****************************************************************************
4296 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4297 ****************************************************************************/
4299 static uint32 map_lock_offset(uint32 high, uint32 low)
4303 uint32 highcopy = high;
4306 * Try and find out how many significant bits there are in high.
4309 for(i = 0; highcopy; i++)
4313 * We use 31 bits not 32 here as POSIX
4314 * lock offsets may not be negative.
4317 mask = (~0) << (31 - i);
4320 return 0; /* Fail. */
4326 #endif /* !defined(HAVE_LONGLONG) */
4328 /****************************************************************************
4329 Get a lock offset, dealing with large offset requests.
4330 ****************************************************************************/
4332 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4334 SMB_BIG_UINT offset = 0;
4338 if(!large_file_format) {
4339 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4342 #if defined(HAVE_LONGLONG)
4343 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4344 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4345 #else /* HAVE_LONGLONG */
4348 * NT4.x seems to be broken in that it sends large file (64 bit)
4349 * lockingX calls even if the CAP_LARGE_FILES was *not*
4350 * negotiated. For boxes without large unsigned ints mangle the
4351 * lock offset by mapping the top 32 bits onto the lower 32.
4354 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4355 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4356 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4359 if((new_low = map_lock_offset(high, low)) == 0) {
4361 return (SMB_BIG_UINT)-1;
4364 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4365 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4366 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4367 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4370 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4371 #endif /* HAVE_LONGLONG */
4377 /****************************************************************************
4378 Reply to a lockingX request.
4379 ****************************************************************************/
4381 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4383 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4384 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4385 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4386 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4387 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4388 SMB_BIG_UINT count = 0, offset = 0;
4390 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4393 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4395 BOOL my_lock_ctx = False;
4398 START_PROFILE(SMBlockingX);
4400 CHECK_FSP(fsp,conn);
4402 data = smb_buf(inbuf);
4404 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4405 /* we don't support these - and CANCEL_LOCK makes w2k
4406 and XP reboot so I don't really want to be
4407 compatible! (tridge) */
4408 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4411 /* Check if this is an oplock break on a file
4412 we have granted an oplock on.
4414 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4415 /* Client can insist on breaking to none. */
4416 BOOL break_to_none = (oplocklevel == 0);
4418 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4419 (unsigned int)oplocklevel, fsp->fnum ));
4422 * Make sure we have granted an exclusive or batch oplock on this file.
4425 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4426 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4427 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4429 /* if this is a pure oplock break request then don't send a reply */
4430 if (num_locks == 0 && num_ulocks == 0) {
4431 END_PROFILE(SMBlockingX);
4434 END_PROFILE(SMBlockingX);
4435 return ERROR_DOS(ERRDOS,ERRlock);
4439 if (remove_oplock(fsp, break_to_none) == False) {
4440 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4444 /* if this is a pure oplock break request then don't send a reply */
4445 if (num_locks == 0 && num_ulocks == 0) {
4446 /* Sanity check - ensure a pure oplock break is not a
4448 if(CVAL(inbuf,smb_vwv0) != 0xff)
4449 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4450 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4451 END_PROFILE(SMBlockingX);
4457 * We do this check *after* we have checked this is not a oplock break
4458 * response message. JRA.
4461 release_level_2_oplocks_on_change(fsp);
4463 /* Data now points at the beginning of the list
4464 of smb_unlkrng structs */
4465 for(i = 0; i < (int)num_ulocks; i++) {
4466 lock_pid = get_lock_pid( data, i, large_file_format);
4467 count = get_lock_count( data, i, large_file_format);
4468 offset = get_lock_offset( data, i, large_file_format, &err);
4471 * There is no error code marked "stupid client bug".... :-).
4474 END_PROFILE(SMBlockingX);
4475 return ERROR_DOS(ERRDOS,ERRnoaccess);
4478 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4479 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4481 status = do_unlock(fsp,conn,lock_pid,count,offset);
4482 if (NT_STATUS_V(status)) {
4483 END_PROFILE(SMBlockingX);
4484 return ERROR_NT(status);
4488 /* Setup the timeout in seconds. */
4490 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4492 /* Now do any requested locks */
4493 data += ((large_file_format ? 20 : 10)*num_ulocks);
4495 /* Data now points at the beginning of the list
4496 of smb_lkrng structs */
4498 for(i = 0; i < (int)num_locks; i++) {
4499 lock_pid = get_lock_pid( data, i, large_file_format);
4500 count = get_lock_count( data, i, large_file_format);
4501 offset = get_lock_offset( data, i, large_file_format, &err);
4504 * There is no error code marked "stupid client bug".... :-).
4507 END_PROFILE(SMBlockingX);
4508 return ERROR_DOS(ERRDOS,ERRnoaccess);
4511 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4512 (double)offset, (double)count, (unsigned int)lock_pid,
4513 fsp->fsp_name, (int)lock_timeout ));
4515 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4516 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4517 if (NT_STATUS_V(status)) {
4519 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4520 * Even if it's our own lock context, we need to wait here as
4521 * there may be an unlock on the way.
4522 * So I removed a "&& !my_lock_ctx" from the following
4523 * if statement. JRA.
4525 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4527 * A blocking lock was requested. Package up
4528 * this smb into a queued request and push it
4529 * onto the blocking lock queue.
4531 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4532 END_PROFILE(SMBlockingX);
4540 /* If any of the above locks failed, then we must unlock
4541 all of the previous locks (X/Open spec). */
4542 if (i != num_locks && num_locks != 0) {
4544 * Ensure we don't do a remove on the lock that just failed,
4545 * as under POSIX rules, if we have a lock already there, we
4546 * will delete it (and we shouldn't) .....
4548 for(i--; i >= 0; i--) {
4549 lock_pid = get_lock_pid( data, i, large_file_format);
4550 count = get_lock_count( data, i, large_file_format);
4551 offset = get_lock_offset( data, i, large_file_format, &err);
4554 * There is no error code marked "stupid client bug".... :-).
4557 END_PROFILE(SMBlockingX);
4558 return ERROR_DOS(ERRDOS,ERRnoaccess);
4561 do_unlock(fsp,conn,lock_pid,count,offset);
4563 END_PROFILE(SMBlockingX);
4564 return ERROR_NT(status);
4567 set_message(outbuf,2,0,True);
4569 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4570 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4572 END_PROFILE(SMBlockingX);
4573 return chain_reply(inbuf,outbuf,length,bufsize);
4576 /****************************************************************************
4577 Reply to a SMBreadbmpx (read block multiplex) request.
4578 ****************************************************************************/
4580 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4591 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4592 START_PROFILE(SMBreadBmpx);
4594 /* this function doesn't seem to work - disable by default */
4595 if (!lp_readbmpx()) {
4596 END_PROFILE(SMBreadBmpx);
4597 return ERROR_DOS(ERRSRV,ERRuseSTD);
4600 outsize = set_message(outbuf,8,0,True);
4602 CHECK_FSP(fsp,conn);
4605 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4606 maxcount = SVAL(inbuf,smb_vwv3);
4608 data = smb_buf(outbuf);
4609 pad = ((long)data)%4;
4614 max_per_packet = bufsize-(outsize+pad);
4618 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4619 END_PROFILE(SMBreadBmpx);
4620 return ERROR_DOS(ERRDOS,ERRlock);
4624 size_t N = MIN(max_per_packet,tcount-total_read);
4626 nread = read_file(fsp,data,startpos,N);
4631 if (nread < (ssize_t)N)
4632 tcount = total_read + nread;
4634 set_message(outbuf,8,nread,False);
4635 SIVAL(outbuf,smb_vwv0,startpos);
4636 SSVAL(outbuf,smb_vwv2,tcount);
4637 SSVAL(outbuf,smb_vwv6,nread);
4638 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4640 if (!send_smb(smbd_server_fd(),outbuf))
4641 exit_server("reply_readbmpx: send_smb failed.");
4643 total_read += nread;
4645 } while (total_read < (ssize_t)tcount);
4647 END_PROFILE(SMBreadBmpx);
4651 /****************************************************************************
4652 Reply to a SMBsetattrE.
4653 ****************************************************************************/
4655 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4657 struct utimbuf unix_times;
4659 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4660 START_PROFILE(SMBsetattrE);
4662 outsize = set_message(outbuf,0,0,True);
4664 if(!fsp || (fsp->conn != conn)) {
4665 END_PROFILE(SMBgetattrE);
4666 return ERROR_DOS(ERRDOS,ERRbadfid);
4670 * Convert the DOS times into unix times. Ignore create
4671 * time as UNIX can't set this.
4674 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4675 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4678 * Patch from Ray Frush <frush@engr.colostate.edu>
4679 * Sometimes times are sent as zero - ignore them.
4682 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4683 /* Ignore request */
4684 if( DEBUGLVL( 3 ) ) {
4685 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4686 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4688 END_PROFILE(SMBsetattrE);
4690 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4691 /* set modify time = to access time if modify time was 0 */
4692 unix_times.modtime = unix_times.actime;
4695 /* Set the date on this file */
4696 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4697 END_PROFILE(SMBsetattrE);
4698 return ERROR_DOS(ERRDOS,ERRnoaccess);
4701 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4702 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4704 END_PROFILE(SMBsetattrE);
4709 /* Back from the dead for OS/2..... JRA. */
4711 /****************************************************************************
4712 Reply to a SMBwritebmpx (write block multiplex primary) request.
4713 ****************************************************************************/
4715 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4718 ssize_t nwritten = -1;
4725 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4726 START_PROFILE(SMBwriteBmpx);
4728 CHECK_FSP(fsp,conn);
4732 tcount = SVAL(inbuf,smb_vwv1);
4733 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4734 write_through = BITSETW(inbuf+smb_vwv7,0);
4735 numtowrite = SVAL(inbuf,smb_vwv10);
4736 smb_doff = SVAL(inbuf,smb_vwv11);
4738 data = smb_base(inbuf) + smb_doff;
4740 /* If this fails we need to send an SMBwriteC response,
4741 not an SMBwritebmpx - set this up now so we don't forget */
4742 SCVAL(outbuf,smb_com,SMBwritec);
4744 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4745 END_PROFILE(SMBwriteBmpx);
4746 return(ERROR_DOS(ERRDOS,ERRlock));
4749 nwritten = write_file(fsp,data,startpos,numtowrite);
4751 if(lp_syncalways(SNUM(conn)) || write_through)
4752 sync_file(conn,fsp);
4754 if(nwritten < (ssize_t)numtowrite) {
4755 END_PROFILE(SMBwriteBmpx);
4756 return(UNIXERROR(ERRHRD,ERRdiskfull));
4759 /* If the maximum to be written to this file
4760 is greater than what we just wrote then set
4761 up a secondary struct to be attached to this
4762 fd, we will use this to cache error messages etc. */
4764 if((ssize_t)tcount > nwritten) {
4765 write_bmpx_struct *wbms;
4766 if(fsp->wbmpx_ptr != NULL)
4767 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4769 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4771 DEBUG(0,("Out of memory in reply_readmpx\n"));
4772 END_PROFILE(SMBwriteBmpx);
4773 return(ERROR_DOS(ERRSRV,ERRnoresource));
4775 wbms->wr_mode = write_through;
4776 wbms->wr_discard = False; /* No errors yet */
4777 wbms->wr_total_written = nwritten;
4778 wbms->wr_errclass = 0;
4780 fsp->wbmpx_ptr = wbms;
4783 /* We are returning successfully, set the message type back to
4785 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4787 outsize = set_message(outbuf,1,0,True);
4789 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4791 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4792 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4794 if (write_through && tcount==nwritten) {
4795 /* We need to send both a primary and a secondary response */
4796 smb_setlen(outbuf,outsize - 4);
4797 if (!send_smb(smbd_server_fd(),outbuf))
4798 exit_server("reply_writebmpx: send_smb failed.");
4800 /* Now the secondary */
4801 outsize = set_message(outbuf,1,0,True);
4802 SCVAL(outbuf,smb_com,SMBwritec);
4803 SSVAL(outbuf,smb_vwv0,nwritten);
4806 END_PROFILE(SMBwriteBmpx);
4810 /****************************************************************************
4811 Reply to a SMBwritebs (write block multiplex secondary) request.
4812 ****************************************************************************/
4814 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4817 ssize_t nwritten = -1;
4824 write_bmpx_struct *wbms;
4825 BOOL send_response = False;
4826 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4827 START_PROFILE(SMBwriteBs);
4829 CHECK_FSP(fsp,conn);
4832 tcount = SVAL(inbuf,smb_vwv1);
4833 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4834 numtowrite = SVAL(inbuf,smb_vwv6);
4835 smb_doff = SVAL(inbuf,smb_vwv7);
4837 data = smb_base(inbuf) + smb_doff;
4839 /* We need to send an SMBwriteC response, not an SMBwritebs */
4840 SCVAL(outbuf,smb_com,SMBwritec);
4842 /* This fd should have an auxiliary struct attached,
4843 check that it does */
4844 wbms = fsp->wbmpx_ptr;
4846 END_PROFILE(SMBwriteBs);
4850 /* If write through is set we can return errors, else we must cache them */
4851 write_through = wbms->wr_mode;
4853 /* Check for an earlier error */
4854 if(wbms->wr_discard) {
4855 END_PROFILE(SMBwriteBs);
4856 return -1; /* Just discard the packet */
4859 nwritten = write_file(fsp,data,startpos,numtowrite);
4861 if(lp_syncalways(SNUM(conn)) || write_through)
4862 sync_file(conn,fsp);
4864 if (nwritten < (ssize_t)numtowrite) {
4866 /* We are returning an error - we can delete the aux struct */
4869 fsp->wbmpx_ptr = NULL;
4870 END_PROFILE(SMBwriteBs);
4871 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4873 END_PROFILE(SMBwriteBs);
4874 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4877 /* Increment the total written, if this matches tcount
4878 we can discard the auxiliary struct (hurrah !) and return a writeC */
4879 wbms->wr_total_written += nwritten;
4880 if(wbms->wr_total_written >= tcount) {
4881 if (write_through) {
4882 outsize = set_message(outbuf,1,0,True);
4883 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4884 send_response = True;
4888 fsp->wbmpx_ptr = NULL;
4892 END_PROFILE(SMBwriteBs);
4896 END_PROFILE(SMBwriteBs);
4900 /****************************************************************************
4901 Reply to a SMBgetattrE.
4902 ****************************************************************************/
4904 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4906 SMB_STRUCT_STAT sbuf;
4909 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4910 START_PROFILE(SMBgetattrE);
4912 outsize = set_message(outbuf,11,0,True);
4914 if(!fsp || (fsp->conn != conn)) {
4915 END_PROFILE(SMBgetattrE);
4916 return ERROR_DOS(ERRDOS,ERRbadfid);
4919 /* Do an fstat on this file */
4920 if(fsp_stat(fsp, &sbuf)) {
4921 END_PROFILE(SMBgetattrE);
4922 return(UNIXERROR(ERRDOS,ERRnoaccess));
4925 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4928 * Convert the times into dos times. Set create
4929 * date to be last modify date as UNIX doesn't save
4933 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4934 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4935 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4938 SIVAL(outbuf,smb_vwv6,0);
4939 SIVAL(outbuf,smb_vwv8,0);
4941 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4942 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4943 SIVAL(outbuf,smb_vwv8,allocation_size);
4945 SSVAL(outbuf,smb_vwv10, mode);
4947 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4949 END_PROFILE(SMBgetattrE);