2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K.
43 We're assuming here that '/' is not the second byte in any multibyte char
44 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
46 ****************************************************************************/
48 static NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
51 const char *s = srcname;
52 NTSTATUS ret = NT_STATUS_OK;
55 if (IS_DIRECTORY_SEP(*s)) {
57 * Safe to assume is not the second part of a mb char as this is handled below.
59 /* Eat multiple '/' or '\\' */
60 while (IS_DIRECTORY_SEP(*s)) {
63 if ((d != destname) && (*s != '\0')) {
64 /* We only care about non-leading or trailing '/' or '\\' */
67 } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
68 /* Uh oh - "../" or "..\\" or "..\0" ! */
71 * No mb char starts with '.' so we're safe checking the directory separator here.
74 /* If we just added a '/', delete it. */
76 if ((d > destname) && (*(d-1) == '/')) {
78 if (d == (destname + 1)) {
84 /* Are we at the start ? Can't go back further if so. */
86 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
88 /* Go back one level... */
89 while (d > destname) {
95 } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
98 * No mb char starts with '.' so we're safe checking the directory separator here.
101 /* "./" or ".\\" fails with a different error depending on where it is... */
104 ret = NT_STATUS_OBJECT_NAME_INVALID;
107 return NT_STATUS_INVALID_PARAMETER;
109 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
113 if ((*s & 0x80) && IS_DIRECTORY_SEP(s[1])) {
115 * Potential mb char with second char a directory separator.
116 * All the encodings we care about are 2 byte only, so do a
117 * conversion to unicode. If the one byte char converts then
118 * it really is a directory separator following. Otherwise if
119 * the two byte character converts (and it should or our assumption
120 * about character sets is broken and we panic) then copy both
121 * bytes as it's a MB character, not a directory separator.
125 if (convert_string(CH_UNIX, CH_UCS2, s, 1, &ucs2_val, 2) == 2) {
127 } else if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) {
130 smb_panic("check_path_syntax: directory separator assumptions invalid !\n");
133 /* Just copy the char (or the second byte of the mb char). */
141 /****************************************************************************
142 Pull a string and check the path - provide for error return.
143 ****************************************************************************/
145 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
148 char *tmppath_ptr = tmppath;
151 SMB_ASSERT(dest_len == sizeof(pstring));
155 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
157 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
159 *err = check_path_syntax(dest, tmppath);
163 /****************************************************************************
164 Reply to a special message.
165 ****************************************************************************/
167 int reply_special(char *inbuf,char *outbuf)
170 int msg_type = CVAL(inbuf,0);
171 int msg_flags = CVAL(inbuf,1);
175 static BOOL already_got_session = False;
179 memset(outbuf,'\0',smb_size);
181 smb_setlen(outbuf,0);
184 case 0x81: /* session request */
186 if (already_got_session) {
187 exit_server("multiple session request not permitted");
190 SCVAL(outbuf,0,0x82);
192 if (name_len(inbuf+4) > 50 ||
193 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
194 DEBUG(0,("Invalid name length in session request\n"));
197 name_extract(inbuf,4,name1);
198 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
199 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
202 set_local_machine_name(name1, True);
203 set_remote_machine_name(name2, True);
205 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
206 get_local_machine_name(), get_remote_machine_name(),
209 if (name_type == 'R') {
210 /* We are being asked for a pathworks session ---
212 SCVAL(outbuf, 0,0x83);
216 /* only add the client's machine name to the list
217 of possibly valid usernames if we are operating
218 in share mode security */
219 if (lp_security() == SEC_SHARE) {
220 add_session_user(get_remote_machine_name());
223 reload_services(True);
226 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
228 already_got_session = True;
231 case 0x89: /* session keepalive request
232 (some old clients produce this?) */
233 SCVAL(outbuf,0,SMBkeepalive);
237 case 0x82: /* positive session response */
238 case 0x83: /* negative session response */
239 case 0x84: /* retarget session response */
240 DEBUG(0,("Unexpected session response\n"));
243 case SMBkeepalive: /* session keepalive */
248 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
249 msg_type, msg_flags));
254 /****************************************************************************
256 ****************************************************************************/
258 int reply_tcon(connection_struct *conn,
259 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
266 uint16 vuid = SVAL(inbuf,smb_uid);
270 DATA_BLOB password_blob;
272 START_PROFILE(SMBtcon);
274 *service_buf = *password = *dev = 0;
276 p = smb_buf(inbuf)+1;
277 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
278 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
280 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
282 p = strrchr_m(service_buf,'\\');
286 service = service_buf;
289 password_blob = data_blob(password, pwlen+1);
291 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
293 data_blob_clear_free(&password_blob);
296 END_PROFILE(SMBtcon);
297 return ERROR_NT(nt_status);
300 outsize = set_message(outbuf,2,0,True);
301 SSVAL(outbuf,smb_vwv0,max_recv);
302 SSVAL(outbuf,smb_vwv1,conn->cnum);
303 SSVAL(outbuf,smb_tid,conn->cnum);
305 DEBUG(3,("tcon service=%s cnum=%d\n",
306 service, conn->cnum));
308 END_PROFILE(SMBtcon);
312 /****************************************************************************
313 Reply to a tcon and X.
314 ****************************************************************************/
316 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
321 /* what the cleint thinks the device is */
322 fstring client_devicetype;
323 /* what the server tells the client the share represents */
324 const char *server_devicetype;
326 uint16 vuid = SVAL(inbuf,smb_uid);
327 int passlen = SVAL(inbuf,smb_vwv3);
330 extern BOOL global_encrypted_passwords_negotiated;
332 START_PROFILE(SMBtconX);
334 *service = *client_devicetype = 0;
336 /* we might have to close an old one */
337 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
338 close_cnum(conn,vuid);
341 if (passlen > MAX_PASS_LEN) {
342 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
345 if (global_encrypted_passwords_negotiated) {
346 password = data_blob(smb_buf(inbuf),passlen);
348 password = data_blob(smb_buf(inbuf),passlen+1);
349 /* Ensure correct termination */
350 password.data[passlen]=0;
353 p = smb_buf(inbuf) + passlen;
354 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
357 * the service name can be either: \\server\share
358 * or share directly like on the DELL PowerVault 705
361 q = strchr_m(path+2,'\\');
363 END_PROFILE(SMBtconX);
364 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
366 fstrcpy(service,q+1);
369 fstrcpy(service,path);
371 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
373 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
375 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
377 data_blob_clear_free(&password);
380 END_PROFILE(SMBtconX);
381 return ERROR_NT(nt_status);
385 server_devicetype = "IPC";
386 else if ( IS_PRINT(conn) )
387 server_devicetype = "LPT1:";
389 server_devicetype = "A:";
391 if (Protocol < PROTOCOL_NT1) {
392 set_message(outbuf,2,0,True);
394 p += srvstr_push(outbuf, p, server_devicetype, -1,
395 STR_TERMINATE|STR_ASCII);
396 set_message_end(outbuf,p);
398 /* NT sets the fstype of IPC$ to the null string */
399 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
401 set_message(outbuf,3,0,True);
404 p += srvstr_push(outbuf, p, server_devicetype, -1,
405 STR_TERMINATE|STR_ASCII);
406 p += srvstr_push(outbuf, p, fstype, -1,
409 set_message_end(outbuf,p);
411 /* what does setting this bit do? It is set by NT4 and
412 may affect the ability to autorun mounted cdroms */
413 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
414 (lp_csc_policy(SNUM(conn)) << 2));
416 init_dfsroot(conn, inbuf, outbuf);
420 DEBUG(3,("tconX service=%s \n",
423 /* set the incoming and outgoing tid to the just created one */
424 SSVAL(inbuf,smb_tid,conn->cnum);
425 SSVAL(outbuf,smb_tid,conn->cnum);
427 END_PROFILE(SMBtconX);
428 return chain_reply(inbuf,outbuf,length,bufsize);
431 /****************************************************************************
432 Reply to an unknown type.
433 ****************************************************************************/
435 int reply_unknown(char *inbuf,char *outbuf)
438 type = CVAL(inbuf,smb_com);
440 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
441 smb_fn_name(type), type, type));
443 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
446 /****************************************************************************
448 ****************************************************************************/
450 int reply_ioctl(connection_struct *conn,
451 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
453 uint16 device = SVAL(inbuf,smb_vwv1);
454 uint16 function = SVAL(inbuf,smb_vwv2);
455 uint32 ioctl_code = (device << 16) + function;
456 int replysize, outsize;
458 START_PROFILE(SMBioctl);
460 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
462 switch (ioctl_code) {
463 case IOCTL_QUERY_JOB_INFO:
467 END_PROFILE(SMBioctl);
468 return(ERROR_DOS(ERRSRV,ERRnosupport));
471 outsize = set_message(outbuf,8,replysize+1,True);
472 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
473 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
474 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
475 p = smb_buf(outbuf) + 1; /* Allow for alignment */
477 switch (ioctl_code) {
478 case IOCTL_QUERY_JOB_INFO:
480 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
482 END_PROFILE(SMBioctl);
483 return(UNIXERROR(ERRDOS,ERRbadfid));
485 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
486 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
487 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
492 END_PROFILE(SMBioctl);
496 /****************************************************************************
498 ****************************************************************************/
500 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
506 BOOL bad_path = False;
507 SMB_STRUCT_STAT sbuf;
510 START_PROFILE(SMBchkpth);
512 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
513 if (!NT_STATUS_IS_OK(status)) {
514 END_PROFILE(SMBchkpth);
515 return ERROR_NT(status);
518 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
520 unix_convert(name,conn,0,&bad_path,&sbuf);
522 mode = SVAL(inbuf,smb_vwv0);
524 if (check_name(name,conn)) {
525 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
526 if (!(ok = S_ISDIR(sbuf.st_mode))) {
527 END_PROFILE(SMBchkpth);
528 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
533 /* We special case this - as when a Windows machine
534 is parsing a path is steps through the components
535 one at a time - if a component fails it expects
536 ERRbadpath, not ERRbadfile.
538 if(errno == ENOENT) {
540 * Windows returns different error codes if
541 * the parent directory is valid but not the
542 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
543 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
544 * if the path is invalid.
547 END_PROFILE(SMBchkpth);
548 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
550 END_PROFILE(SMBchkpth);
551 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
553 } else if (errno == ENOTDIR) {
554 END_PROFILE(SMBchkpth);
555 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
558 END_PROFILE(SMBchkpth);
559 return(UNIXERROR(ERRDOS,ERRbadpath));
562 outsize = set_message(outbuf,0,0,True);
564 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
566 END_PROFILE(SMBchkpth);
570 /****************************************************************************
572 ****************************************************************************/
574 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
578 SMB_STRUCT_STAT sbuf;
583 BOOL bad_path = False;
587 START_PROFILE(SMBgetatr);
589 p = smb_buf(inbuf) + 1;
590 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
591 if (!NT_STATUS_IS_OK(status)) {
592 END_PROFILE(SMBgetatr);
593 return ERROR_NT(status);
596 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
598 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
599 under WfWg - weird! */
601 mode = aHIDDEN | aDIR;
602 if (!CAN_WRITE(conn))
608 unix_convert(fname,conn,0,&bad_path,&sbuf);
609 if (check_name(fname,conn)) {
610 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
611 mode = dos_mode(conn,fname,&sbuf);
613 mtime = sbuf.st_mtime;
618 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
624 END_PROFILE(SMBgetatr);
625 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
628 outsize = set_message(outbuf,10,0,True);
630 SSVAL(outbuf,smb_vwv0,mode);
631 if(lp_dos_filetime_resolution(SNUM(conn)) )
632 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
634 put_dos_date3(outbuf,smb_vwv1,mtime);
635 SIVAL(outbuf,smb_vwv3,(uint32)size);
637 if (Protocol >= PROTOCOL_NT1)
638 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
640 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
642 END_PROFILE(SMBgetatr);
646 /****************************************************************************
648 ****************************************************************************/
650 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
657 SMB_STRUCT_STAT sbuf;
658 BOOL bad_path = False;
662 START_PROFILE(SMBsetatr);
664 p = smb_buf(inbuf) + 1;
665 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
666 if (!NT_STATUS_IS_OK(status)) {
667 END_PROFILE(SMBsetatr);
668 return ERROR_NT(status);
671 unix_convert(fname,conn,0,&bad_path,&sbuf);
673 mode = SVAL(inbuf,smb_vwv0);
674 mtime = make_unix_date3(inbuf+smb_vwv1);
676 if (mode != FILE_ATTRIBUTE_NORMAL) {
677 if (VALID_STAT_OF_DIR(sbuf))
682 if (check_name(fname,conn))
683 ok = (file_chmod(conn,fname,mode,NULL) == 0);
689 ok = set_filetime(conn,fname,mtime);
692 END_PROFILE(SMBsetatr);
693 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
696 outsize = set_message(outbuf,0,0,True);
698 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
700 END_PROFILE(SMBsetatr);
704 /****************************************************************************
706 ****************************************************************************/
708 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
711 SMB_BIG_UINT dfree,dsize,bsize;
712 START_PROFILE(SMBdskattr);
714 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
716 outsize = set_message(outbuf,5,0,True);
718 if (Protocol <= PROTOCOL_LANMAN2) {
719 double total_space, free_space;
720 /* we need to scale this to a number that DOS6 can handle. We
721 use floating point so we can handle large drives on systems
722 that don't have 64 bit integers
724 we end up displaying a maximum of 2G to DOS systems
726 total_space = dsize * (double)bsize;
727 free_space = dfree * (double)bsize;
729 dsize = (total_space+63*512) / (64*512);
730 dfree = (free_space+63*512) / (64*512);
732 if (dsize > 0xFFFF) dsize = 0xFFFF;
733 if (dfree > 0xFFFF) dfree = 0xFFFF;
735 SSVAL(outbuf,smb_vwv0,dsize);
736 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
737 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
738 SSVAL(outbuf,smb_vwv3,dfree);
740 SSVAL(outbuf,smb_vwv0,dsize);
741 SSVAL(outbuf,smb_vwv1,bsize/512);
742 SSVAL(outbuf,smb_vwv2,512);
743 SSVAL(outbuf,smb_vwv3,dfree);
746 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
748 END_PROFILE(SMBdskattr);
752 /****************************************************************************
754 Can be called from SMBsearch, SMBffirst or SMBfunique.
755 ****************************************************************************/
757 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
767 unsigned int numentries = 0;
768 unsigned int maxentries = 0;
769 BOOL finished = False;
776 BOOL check_descend = False;
777 BOOL expect_close = False;
778 BOOL can_open = True;
779 BOOL bad_path = False;
781 START_PROFILE(SMBsearch);
783 *mask = *directory = *fname = 0;
785 /* If we were called as SMBffirst then we must expect close. */
786 if(CVAL(inbuf,smb_com) == SMBffirst)
789 outsize = set_message(outbuf,1,3,True);
790 maxentries = SVAL(inbuf,smb_vwv0);
791 dirtype = SVAL(inbuf,smb_vwv1);
792 p = smb_buf(inbuf) + 1;
793 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
794 if (!NT_STATUS_IS_OK(nt_status)) {
795 END_PROFILE(SMBsearch);
796 return ERROR_NT(nt_status);
799 status_len = SVAL(p, 0);
802 /* dirtype &= ~aDIR; */
804 if (status_len == 0) {
805 SMB_STRUCT_STAT sbuf;
808 pstrcpy(directory,path);
810 unix_convert(directory,conn,0,&bad_path,&sbuf);
813 if (!check_name(directory,conn))
816 p = strrchr_m(dir2,'/');
825 p = strrchr_m(directory,'/');
831 if (strlen(directory) == 0)
832 pstrcpy(directory,".");
833 memset((char *)status,'\0',21);
834 SCVAL(status,0,(dirtype & 0x1F));
839 status_dirtype = CVAL(status,0) & 0x1F;
840 if (status_dirtype != (dirtype & 0x1F))
841 dirtype = status_dirtype;
843 conn->dirptr = dptr_fetch(status+12,&dptr_num);
846 string_set(&conn->dirpath,dptr_path(dptr_num));
847 pstrcpy(mask, dptr_wcard(dptr_num));
851 p = smb_buf(outbuf) + 3;
854 if (status_len == 0) {
855 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
858 END_PROFILE(SMBsearch);
859 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
861 END_PROFILE(SMBsearch);
862 return ERROR_DOS(ERRDOS,ERRnofids);
864 dptr_set_wcard(dptr_num, strdup(mask));
865 dptr_set_attr(dptr_num, dirtype);
867 dirtype = dptr_attr(dptr_num);
870 DEBUG(4,("dptr_num is %d\n",dptr_num));
873 if ((dirtype&0x1F) == aVOLID) {
875 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
876 dptr_fill(p+12,dptr_num);
877 if (dptr_zero(p+12) && (status_len==0))
881 p += DIR_STRUCT_SIZE;
884 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
886 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
887 conn->dirpath,lp_dontdescend(SNUM(conn))));
888 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
889 check_descend = True;
891 for (i=numentries;(i<maxentries) && !finished;i++) {
892 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
895 make_dir_struct(p,mask,fname,size,mode,date);
896 dptr_fill(p+12,dptr_num);
899 p += DIR_STRUCT_SIZE;
908 /* If we were called as SMBffirst with smb_search_id == NULL
909 and no entries were found then return error and close dirptr
912 if(ok && expect_close && numentries == 0 && status_len == 0) {
913 if (Protocol < PROTOCOL_NT1) {
914 SCVAL(outbuf,smb_rcls,ERRDOS);
915 SSVAL(outbuf,smb_err,ERRnofiles);
917 /* Also close the dptr - we know it's gone */
918 dptr_close(&dptr_num);
919 } else if (numentries == 0 || !ok) {
920 if (Protocol < PROTOCOL_NT1) {
921 SCVAL(outbuf,smb_rcls,ERRDOS);
922 SSVAL(outbuf,smb_err,ERRnofiles);
924 dptr_close(&dptr_num);
927 /* If we were called as SMBfunique, then we can close the dirptr now ! */
928 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
929 dptr_close(&dptr_num);
931 SSVAL(outbuf,smb_vwv0,numentries);
932 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
933 SCVAL(smb_buf(outbuf),0,5);
934 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
936 if (Protocol >= PROTOCOL_NT1)
937 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
939 outsize += DIR_STRUCT_SIZE*numentries;
940 smb_setlen(outbuf,outsize - 4);
942 if ((! *directory) && dptr_path(dptr_num))
943 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
945 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
946 smb_fn_name(CVAL(inbuf,smb_com)),
947 mask, directory, dirtype, numentries, maxentries ) );
949 END_PROFILE(SMBsearch);
953 /****************************************************************************
954 Reply to a fclose (stop directory search).
955 ****************************************************************************/
957 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
967 START_PROFILE(SMBfclose);
969 outsize = set_message(outbuf,1,0,True);
970 p = smb_buf(inbuf) + 1;
971 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
972 if (!NT_STATUS_IS_OK(err)) {
973 END_PROFILE(SMBfclose);
974 return ERROR_NT(err);
977 status_len = SVAL(p,0);
980 if (status_len == 0) {
981 END_PROFILE(SMBfclose);
982 return ERROR_DOS(ERRSRV,ERRsrverror);
987 if(dptr_fetch(status+12,&dptr_num)) {
988 /* Close the dptr - we know it's gone */
989 dptr_close(&dptr_num);
992 SSVAL(outbuf,smb_vwv0,0);
994 DEBUG(3,("search close\n"));
996 END_PROFILE(SMBfclose);
1000 /****************************************************************************
1002 ****************************************************************************/
1004 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1014 SMB_STRUCT_STAT sbuf;
1015 BOOL bad_path = False;
1017 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1019 START_PROFILE(SMBopen);
1021 share_mode = SVAL(inbuf,smb_vwv0);
1023 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 END_PROFILE(SMBopen);
1026 return ERROR_NT(status);
1029 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1031 unix_convert(fname,conn,0,&bad_path,&sbuf);
1033 unixmode = unix_mode(conn,aARCH,fname);
1035 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1036 unixmode, oplock_request,&rmode,NULL);
1039 END_PROFILE(SMBopen);
1040 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1043 size = sbuf.st_size;
1044 fmode = dos_mode(conn,fname,&sbuf);
1045 mtime = sbuf.st_mtime;
1048 DEBUG(3,("attempt to open a directory %s\n",fname));
1049 close_file(fsp,False);
1050 END_PROFILE(SMBopen);
1051 return ERROR_DOS(ERRDOS,ERRnoaccess);
1054 outsize = set_message(outbuf,7,0,True);
1055 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1056 SSVAL(outbuf,smb_vwv1,fmode);
1057 if(lp_dos_filetime_resolution(SNUM(conn)) )
1058 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1060 put_dos_date3(outbuf,smb_vwv2,mtime);
1061 SIVAL(outbuf,smb_vwv4,(uint32)size);
1062 SSVAL(outbuf,smb_vwv6,rmode);
1064 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1065 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1067 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1068 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1069 END_PROFILE(SMBopen);
1073 /****************************************************************************
1074 Reply to an open and X.
1075 ****************************************************************************/
1077 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1080 int smb_mode = SVAL(inbuf,smb_vwv3);
1081 int smb_attr = SVAL(inbuf,smb_vwv5);
1082 /* Breakout the oplock request bits so we can set the
1083 reply bits separately. */
1084 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1085 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1086 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1088 int open_flags = SVAL(inbuf,smb_vwv2);
1089 int smb_sattr = SVAL(inbuf,smb_vwv4);
1090 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1092 int smb_ofun = SVAL(inbuf,smb_vwv8);
1095 int fmode=0,mtime=0,rmode=0;
1096 SMB_STRUCT_STAT sbuf;
1098 BOOL bad_path = False;
1101 START_PROFILE(SMBopenX);
1103 /* If it's an IPC, pass off the pipe handler. */
1105 if (lp_nt_pipe_support()) {
1106 END_PROFILE(SMBopenX);
1107 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1109 END_PROFILE(SMBopenX);
1110 return ERROR_DOS(ERRSRV,ERRaccess);
1114 /* XXXX we need to handle passed times, sattr and flags */
1115 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 END_PROFILE(SMBopenX);
1118 return ERROR_NT(status);
1121 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1123 unix_convert(fname,conn,0,&bad_path,&sbuf);
1125 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1127 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1128 oplock_request, &rmode,&smb_action);
1131 END_PROFILE(SMBopenX);
1132 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1135 size = sbuf.st_size;
1136 fmode = dos_mode(conn,fname,&sbuf);
1137 mtime = sbuf.st_mtime;
1139 close_file(fsp,False);
1140 END_PROFILE(SMBopenX);
1141 return ERROR_DOS(ERRDOS,ERRnoaccess);
1144 /* If the caller set the extended oplock request bit
1145 and we granted one (by whatever means) - set the
1146 correct bit for extended oplock reply.
1149 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1150 smb_action |= EXTENDED_OPLOCK_GRANTED;
1152 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1153 smb_action |= EXTENDED_OPLOCK_GRANTED;
1155 /* If the caller set the core oplock request bit
1156 and we granted one (by whatever means) - set the
1157 correct bit for core oplock reply.
1160 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1161 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1163 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1164 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1166 set_message(outbuf,15,0,True);
1167 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1168 SSVAL(outbuf,smb_vwv3,fmode);
1169 if(lp_dos_filetime_resolution(SNUM(conn)) )
1170 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1172 put_dos_date3(outbuf,smb_vwv4,mtime);
1173 SIVAL(outbuf,smb_vwv6,(uint32)size);
1174 SSVAL(outbuf,smb_vwv8,rmode);
1175 SSVAL(outbuf,smb_vwv11,smb_action);
1177 END_PROFILE(SMBopenX);
1178 return chain_reply(inbuf,outbuf,length,bufsize);
1181 /****************************************************************************
1182 Reply to a SMBulogoffX.
1183 ****************************************************************************/
1185 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1187 uint16 vuid = SVAL(inbuf,smb_uid);
1188 user_struct *vuser = get_valid_user_struct(vuid);
1189 START_PROFILE(SMBulogoffX);
1192 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1194 /* in user level security we are supposed to close any files
1195 open by this user */
1196 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1197 file_close_user(vuid);
1199 invalidate_vuid(vuid);
1201 set_message(outbuf,2,0,True);
1203 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1205 END_PROFILE(SMBulogoffX);
1206 return chain_reply(inbuf,outbuf,length,bufsize);
1209 /****************************************************************************
1210 Reply to a mknew or a create.
1211 ****************************************************************************/
1213 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1221 BOOL bad_path = False;
1223 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1224 SMB_STRUCT_STAT sbuf;
1226 START_PROFILE(SMBcreate);
1228 com = SVAL(inbuf,smb_com);
1230 createmode = SVAL(inbuf,smb_vwv0);
1231 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1232 if (!NT_STATUS_IS_OK(status)) {
1233 END_PROFILE(SMBcreate);
1234 return ERROR_NT(status);
1237 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1239 unix_convert(fname,conn,0,&bad_path,&sbuf);
1241 if (createmode & aVOLID)
1242 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1244 unixmode = unix_mode(conn,createmode,fname);
1246 if(com == SMBmknew) {
1247 /* We should fail if file exists. */
1248 ofun = FILE_CREATE_IF_NOT_EXIST;
1250 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1251 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1254 /* Open file in dos compatibility share mode. */
1255 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1256 ofun, unixmode, oplock_request, NULL, NULL);
1259 END_PROFILE(SMBcreate);
1260 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1263 outsize = set_message(outbuf,1,0,True);
1264 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1267 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1269 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1270 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1272 DEBUG( 2, ( "new file %s\n", fname ) );
1273 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1275 END_PROFILE(SMBcreate);
1279 /****************************************************************************
1280 Reply to a create temporary file.
1281 ****************************************************************************/
1283 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 createmode = 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 unixmode = unix_mode(conn,createmode,fname);
1313 tmpfd = smb_mkstemp(fname);
1315 END_PROFILE(SMBctemp);
1316 return(UNIXERROR(ERRDOS,ERRnoaccess));
1319 SMB_VFS_STAT(conn,fname,&sbuf);
1321 /* Open file in dos compatibility share mode. */
1322 /* We should fail if file does not exist. */
1323 fsp = open_file_shared(conn,fname,&sbuf,
1324 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1325 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1326 unixmode, oplock_request, NULL, NULL);
1328 /* close fd from smb_mkstemp() */
1332 END_PROFILE(SMBctemp);
1333 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1336 outsize = set_message(outbuf,1,0,True);
1337 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1339 /* the returned filename is relative to the directory */
1340 s = strrchr_m(fname, '/');
1346 p = smb_buf(outbuf);
1347 SSVALS(p, 0, -1); /* what is this? not in spec */
1348 SSVAL(p, 2, strlen(s));
1350 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1351 outsize = set_message_end(outbuf, p);
1353 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1354 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1356 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1357 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1359 DEBUG( 2, ( "created temp file %s\n", fname ) );
1360 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1361 fname, fsp->fd, createmode, (int)unixmode ) );
1363 END_PROFILE(SMBctemp);
1367 /*******************************************************************
1368 Check if a user is allowed to rename a file.
1369 ********************************************************************/
1371 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1377 if (!CAN_WRITE(conn))
1378 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1380 if (S_ISDIR(pst->st_mode))
1381 return NT_STATUS_OK;
1383 /* We need a better way to return NT status codes from open... */
1387 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1388 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1391 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1392 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1393 ret = NT_STATUS_SHARING_VIOLATION;
1396 unix_ERR_ntstatus = NT_STATUS_OK;
1399 close_file(fsp,False);
1400 return NT_STATUS_OK;
1403 /*******************************************************************
1404 Check if a user is allowed to delete a file.
1405 ********************************************************************/
1407 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1409 SMB_STRUCT_STAT sbuf;
1415 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1418 if (!CAN_WRITE(conn))
1419 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1421 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1422 if(errno == ENOENT) {
1424 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1426 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1428 return map_nt_error_from_unix(errno);
1431 fmode = dos_mode(conn,fname,&sbuf);
1433 /* Can't delete a directory. */
1435 return NT_STATUS_FILE_IS_A_DIRECTORY;
1437 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1438 return NT_STATUS_OBJECT_NAME_INVALID;
1439 #endif /* JRATEST */
1441 if (!lp_delete_readonly(SNUM(conn))) {
1443 return NT_STATUS_CANNOT_DELETE;
1445 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1446 return NT_STATUS_NO_SUCH_FILE;
1448 /* We need a better way to return NT status codes from open... */
1452 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1453 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1456 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1457 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1458 ret = unix_ERR_ntstatus;
1459 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1460 ret = NT_STATUS_SHARING_VIOLATION;
1463 unix_ERR_ntstatus = NT_STATUS_OK;
1466 close_file(fsp,False);
1467 return NT_STATUS_OK;
1470 /****************************************************************************
1471 The guts of the unlink command, split out so it may be called by the NT SMB
1473 ****************************************************************************/
1475 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1481 NTSTATUS error = NT_STATUS_OK;
1483 BOOL bad_path = False;
1485 SMB_STRUCT_STAT sbuf;
1487 *directory = *mask = 0;
1489 /* We must check for wildcards in the name given
1490 * directly by the client - before any unmangling.
1491 * This prevents an unmangling of a UNIX name containing
1492 * a DOS wildcard like '*' or '?' from unmangling into
1493 * a wildcard delete which was not intended.
1494 * FIX for #226. JRA.
1497 has_wild = ms_has_wild(name);
1499 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1501 p = strrchr_m(name,'/');
1503 pstrcpy(directory,".");
1507 pstrcpy(directory,name);
1512 * We should only check the mangled cache
1513 * here if unix_convert failed. This means
1514 * that the path in 'mask' doesn't exist
1515 * on the file system and so we need to look
1516 * for a possible mangle. This patch from
1517 * Tine Smukavec <valentin.smukavec@hermes.si>.
1520 if (!rc && mangle_is_mangled(mask))
1521 mangle_check_cache( mask );
1524 pstrcat(directory,"/");
1525 pstrcat(directory,mask);
1526 error = can_delete(directory,conn,dirtype,bad_path);
1527 if (!NT_STATUS_IS_OK(error))
1530 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1534 void *dirptr = NULL;
1537 if (check_name(directory,conn))
1538 dirptr = OpenDir(conn, directory, True);
1540 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1541 the pattern matches against the long name, otherwise the short name
1542 We don't implement this yet XXXX
1546 error = NT_STATUS_NO_SUCH_FILE;
1548 if (strequal(mask,"????????.???"))
1551 while ((dname = ReadDirName(dirptr))) {
1553 BOOL sys_direntry = False;
1554 pstrcpy(fname,dname);
1556 /* Quick check for "." and ".." */
1557 if (fname[0] == '.') {
1558 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1559 if ((dirtype & aDIR)) {
1560 sys_direntry = True;
1567 if(!mask_match(fname, mask, case_sensitive))
1571 error = NT_STATUS_OBJECT_NAME_INVALID;
1575 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1576 error = can_delete(fname,conn,dirtype,bad_path);
1577 if (!NT_STATUS_IS_OK(error))
1579 if (SMB_VFS_UNLINK(conn,fname) == 0)
1581 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1587 if (count == 0 && NT_STATUS_IS_OK(error)) {
1588 error = map_nt_error_from_unix(errno);
1594 /****************************************************************************
1596 ****************************************************************************/
1598 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1605 START_PROFILE(SMBunlink);
1607 dirtype = SVAL(inbuf,smb_vwv0);
1609 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 END_PROFILE(SMBunlink);
1612 return ERROR_NT(status);
1615 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1617 DEBUG(3,("reply_unlink : %s\n",name));
1619 status = unlink_internals(conn, dirtype, name);
1620 if (!NT_STATUS_IS_OK(status))
1621 return ERROR_NT(status);
1624 * Win2k needs a changenotify request response before it will
1625 * update after a rename..
1627 process_pending_change_notify_queue((time_t)0);
1629 outsize = set_message(outbuf,0,0,True);
1631 END_PROFILE(SMBunlink);
1635 /****************************************************************************
1637 ****************************************************************************/
1639 void fail_readraw(void)
1642 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1644 exit_server(errstr);
1647 /****************************************************************************
1648 Use sendfile in readbraw.
1649 ****************************************************************************/
1651 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1652 ssize_t mincount, char *outbuf)
1656 #if defined(WITH_SENDFILE)
1658 * We can only use sendfile on a non-chained packet and on a file
1659 * that is exclusively oplocked. reply_readbraw has already checked the length.
1662 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1663 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1666 _smb_setlen(outbuf,nread);
1667 header.data = outbuf;
1671 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1673 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1674 * return ENOSYS then pretend we just got a normal read.
1676 if (errno == ENOSYS)
1679 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1680 fsp->fsp_name, strerror(errno) ));
1681 exit_server("send_file_readbraw sendfile failed");
1690 ret = read_file(fsp,outbuf+4,startpos,nread);
1691 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1700 _smb_setlen(outbuf,ret);
1701 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1705 /****************************************************************************
1706 Reply to a readbraw (core+ protocol).
1707 ****************************************************************************/
1709 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1711 extern struct current_user current_user;
1712 ssize_t maxcount,mincount;
1715 char *header = outbuf;
1717 START_PROFILE(SMBreadbraw);
1719 if (srv_is_signing_active()) {
1720 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1724 * Special check if an oplock break has been issued
1725 * and the readraw request croses on the wire, we must
1726 * return a zero length response here.
1729 if(global_oplock_break) {
1730 _smb_setlen(header,0);
1731 if (write_data(smbd_server_fd(),header,4) != 4)
1733 DEBUG(5,("readbraw - oplock break finished\n"));
1734 END_PROFILE(SMBreadbraw);
1738 fsp = file_fsp(inbuf,smb_vwv0);
1740 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1742 * fsp could be NULL here so use the value from the packet. JRA.
1744 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1745 _smb_setlen(header,0);
1746 if (write_data(smbd_server_fd(),header,4) != 4)
1748 END_PROFILE(SMBreadbraw);
1752 CHECK_FSP(fsp,conn);
1754 flush_write_cache(fsp, READRAW_FLUSH);
1756 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1757 if(CVAL(inbuf,smb_wct) == 10) {
1759 * This is a large offset (64 bit) read.
1761 #ifdef LARGE_SMB_OFF_T
1763 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1765 #else /* !LARGE_SMB_OFF_T */
1768 * Ensure we haven't been sent a >32 bit offset.
1771 if(IVAL(inbuf,smb_vwv8) != 0) {
1772 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1773 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1774 _smb_setlen(header,0);
1775 if (write_data(smbd_server_fd(),header,4) != 4)
1777 END_PROFILE(SMBreadbraw);
1781 #endif /* LARGE_SMB_OFF_T */
1784 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1785 _smb_setlen(header,0);
1786 if (write_data(smbd_server_fd(),header,4) != 4)
1788 END_PROFILE(SMBreadbraw);
1792 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1793 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1795 /* ensure we don't overrun the packet size */
1796 maxcount = MIN(65535,maxcount);
1798 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1799 SMB_OFF_T size = fsp->size;
1800 SMB_OFF_T sizeneeded = startpos + maxcount;
1802 if (size < sizeneeded) {
1804 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1806 if (!fsp->can_write)
1810 if (startpos >= size)
1813 nread = MIN(maxcount,(size - startpos));
1816 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1817 if (nread < mincount)
1821 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1822 (int)maxcount, (int)mincount, (int)nread ) );
1824 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1826 DEBUG(5,("readbraw finished\n"));
1827 END_PROFILE(SMBreadbraw);
1831 /****************************************************************************
1832 Reply to a lockread (core+ protocol).
1833 ****************************************************************************/
1835 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1843 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1844 BOOL my_lock_ctx = False;
1845 START_PROFILE(SMBlockread);
1847 CHECK_FSP(fsp,conn);
1850 release_level_2_oplocks_on_change(fsp);
1852 numtoread = SVAL(inbuf,smb_vwv1);
1853 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1855 outsize = set_message(outbuf,5,3,True);
1856 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1857 data = smb_buf(outbuf) + 3;
1860 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1861 * protocol request that predates the read/write lock concept.
1862 * Thus instead of asking for a read lock here we need to ask
1863 * for a write lock. JRA.
1864 * Note that the requested lock size is unaffected by max_recv.
1867 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1868 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1870 if (NT_STATUS_V(status)) {
1873 * We used to make lockread a blocking lock. It turns out
1874 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1878 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1880 * A blocking lock was requested. Package up
1881 * this smb into a queued request and push it
1882 * onto the blocking lock queue.
1884 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1885 (SMB_BIG_UINT)numtoread)) {
1886 END_PROFILE(SMBlockread);
1891 END_PROFILE(SMBlockread);
1892 return ERROR_NT(status);
1896 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1899 if (numtoread > max_recv) {
1900 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1901 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1902 (unsigned int)numtoread, (unsigned int)max_recv ));
1903 numtoread = MIN(numtoread,max_recv);
1905 nread = read_file(fsp,data,startpos,numtoread);
1908 END_PROFILE(SMBlockread);
1909 return(UNIXERROR(ERRDOS,ERRnoaccess));
1913 SSVAL(outbuf,smb_vwv0,nread);
1914 SSVAL(outbuf,smb_vwv5,nread+3);
1915 SSVAL(smb_buf(outbuf),1,nread);
1917 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1918 fsp->fnum, (int)numtoread, (int)nread));
1920 END_PROFILE(SMBlockread);
1924 /****************************************************************************
1926 ****************************************************************************/
1928 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1935 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1936 START_PROFILE(SMBread);
1938 CHECK_FSP(fsp,conn);
1941 numtoread = SVAL(inbuf,smb_vwv1);
1942 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1944 outsize = set_message(outbuf,5,3,True);
1945 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1947 * The requested read size cannot be greater than max_recv. JRA.
1949 if (numtoread > max_recv) {
1950 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1951 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1952 (unsigned int)numtoread, (unsigned int)max_recv ));
1953 numtoread = MIN(numtoread,max_recv);
1956 data = smb_buf(outbuf) + 3;
1958 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1959 END_PROFILE(SMBread);
1960 return ERROR_DOS(ERRDOS,ERRlock);
1964 nread = read_file(fsp,data,startpos,numtoread);
1967 END_PROFILE(SMBread);
1968 return(UNIXERROR(ERRDOS,ERRnoaccess));
1972 SSVAL(outbuf,smb_vwv0,nread);
1973 SSVAL(outbuf,smb_vwv5,nread+3);
1974 SCVAL(smb_buf(outbuf),0,1);
1975 SSVAL(smb_buf(outbuf),1,nread);
1977 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1978 fsp->fnum, (int)numtoread, (int)nread ) );
1980 END_PROFILE(SMBread);
1984 /****************************************************************************
1985 Reply to a read and X - possibly using sendfile.
1986 ****************************************************************************/
1988 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1989 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1992 char *data = smb_buf(outbuf);
1994 #if defined(WITH_SENDFILE)
1996 * We can only use sendfile on a non-chained packet and on a file
1997 * that is exclusively oplocked.
2000 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2001 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2002 SMB_STRUCT_STAT sbuf;
2005 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2006 return(UNIXERROR(ERRDOS,ERRnoaccess));
2008 if (startpos > sbuf.st_size)
2011 if (smb_maxcnt > (sbuf.st_size - startpos))
2012 smb_maxcnt = (sbuf.st_size - startpos);
2014 if (smb_maxcnt == 0)
2018 * Set up the packet header before send. We
2019 * assume here the sendfile will work (get the
2020 * correct amount of data).
2023 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2024 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2025 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2026 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2027 SCVAL(outbuf,smb_vwv0,0xFF);
2028 set_message(outbuf,12,smb_maxcnt,False);
2029 header.data = outbuf;
2030 header.length = data - outbuf;
2033 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2035 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2036 * return ENOSYS then pretend we just got a normal read.
2038 if (errno == ENOSYS)
2041 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2042 fsp->fsp_name, strerror(errno) ));
2043 exit_server("send_file_readX sendfile failed");
2046 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2047 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2055 nread = read_file(fsp,data,startpos,smb_maxcnt);
2058 END_PROFILE(SMBreadX);
2059 return(UNIXERROR(ERRDOS,ERRnoaccess));
2062 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2063 SSVAL(outbuf,smb_vwv5,nread);
2064 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2065 SSVAL(smb_buf(outbuf),-2,nread);
2067 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2068 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2073 /****************************************************************************
2074 Reply to a read and X.
2075 ****************************************************************************/
2077 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2079 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2080 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2082 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2084 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2087 START_PROFILE(SMBreadX);
2089 /* If it's an IPC, pass off the pipe handler. */
2091 END_PROFILE(SMBreadX);
2092 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2095 CHECK_FSP(fsp,conn);
2098 set_message(outbuf,12,0,True);
2100 if(CVAL(inbuf,smb_wct) == 12) {
2101 #ifdef LARGE_SMB_OFF_T
2103 * This is a large offset (64 bit) read.
2105 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2107 #else /* !LARGE_SMB_OFF_T */
2110 * Ensure we haven't been sent a >32 bit offset.
2113 if(IVAL(inbuf,smb_vwv10) != 0) {
2114 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2115 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2116 END_PROFILE(SMBreadX);
2117 return ERROR_DOS(ERRDOS,ERRbadaccess);
2120 #endif /* LARGE_SMB_OFF_T */
2124 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2125 END_PROFILE(SMBreadX);
2126 return ERROR_DOS(ERRDOS,ERRlock);
2129 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2131 nread = chain_reply(inbuf,outbuf,length,bufsize);
2133 END_PROFILE(SMBreadX);
2137 /****************************************************************************
2138 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2139 ****************************************************************************/
2141 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2144 ssize_t total_written=0;
2145 size_t numtowrite=0;
2150 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2152 START_PROFILE(SMBwritebraw);
2154 if (srv_is_signing_active()) {
2155 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2158 CHECK_FSP(fsp,conn);
2161 tcount = IVAL(inbuf,smb_vwv1);
2162 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2163 write_through = BITSETW(inbuf+smb_vwv7,0);
2165 /* We have to deal with slightly different formats depending
2166 on whether we are using the core+ or lanman1.0 protocol */
2168 if(Protocol <= PROTOCOL_COREPLUS) {
2169 numtowrite = SVAL(smb_buf(inbuf),-2);
2170 data = smb_buf(inbuf);
2172 numtowrite = SVAL(inbuf,smb_vwv10);
2173 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2176 /* force the error type */
2177 SCVAL(inbuf,smb_com,SMBwritec);
2178 SCVAL(outbuf,smb_com,SMBwritec);
2180 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2181 END_PROFILE(SMBwritebraw);
2182 return(ERROR_DOS(ERRDOS,ERRlock));
2186 nwritten = write_file(fsp,data,startpos,numtowrite);
2188 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2189 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2191 if (nwritten < (ssize_t)numtowrite) {
2192 END_PROFILE(SMBwritebraw);
2193 return(UNIXERROR(ERRHRD,ERRdiskfull));
2196 total_written = nwritten;
2198 /* Return a message to the redirector to tell it to send more bytes */
2199 SCVAL(outbuf,smb_com,SMBwritebraw);
2200 SSVALS(outbuf,smb_vwv0,-1);
2201 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2202 if (!send_smb(smbd_server_fd(),outbuf))
2203 exit_server("reply_writebraw: send_smb failed.");
2205 /* Now read the raw data into the buffer and write it */
2206 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2207 exit_server("secondary writebraw failed");
2210 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2211 numtowrite = smb_len(inbuf);
2213 /* Set up outbuf to return the correct return */
2214 outsize = set_message(outbuf,1,0,True);
2215 SCVAL(outbuf,smb_com,SMBwritec);
2216 SSVAL(outbuf,smb_vwv0,total_written);
2218 if (numtowrite != 0) {
2220 if (numtowrite > BUFFER_SIZE) {
2221 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2222 (unsigned int)numtowrite ));
2223 exit_server("secondary writebraw failed");
2226 if (tcount > nwritten+numtowrite) {
2227 DEBUG(3,("Client overestimated the write %d %d %d\n",
2228 (int)tcount,(int)nwritten,(int)numtowrite));
2231 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2232 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2234 exit_server("secondary writebraw failed");
2237 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2239 if (nwritten < (ssize_t)numtowrite) {
2240 SCVAL(outbuf,smb_rcls,ERRHRD);
2241 SSVAL(outbuf,smb_err,ERRdiskfull);
2245 total_written += nwritten;
2248 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2249 sync_file(conn,fsp);
2251 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2252 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2254 /* we won't return a status if write through is not selected - this follows what WfWg does */
2255 END_PROFILE(SMBwritebraw);
2256 if (!write_through && total_written==tcount) {
2258 #if RABBIT_PELLET_FIX
2260 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2261 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2263 if (!send_keepalive(smbd_server_fd()))
2264 exit_server("reply_writebraw: send of keepalive failed");
2272 /****************************************************************************
2273 Reply to a writeunlock (core+).
2274 ****************************************************************************/
2276 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2277 int size, int dum_buffsize)
2279 ssize_t nwritten = -1;
2283 NTSTATUS status = NT_STATUS_OK;
2284 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2286 START_PROFILE(SMBwriteunlock);
2288 CHECK_FSP(fsp,conn);
2291 numtowrite = SVAL(inbuf,smb_vwv1);
2292 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2293 data = smb_buf(inbuf) + 3;
2295 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2296 WRITE_LOCK,False)) {
2297 END_PROFILE(SMBwriteunlock);
2298 return ERROR_DOS(ERRDOS,ERRlock);
2301 /* The special X/Open SMB protocol handling of
2302 zero length writes is *NOT* done for
2307 nwritten = write_file(fsp,data,startpos,numtowrite);
2309 if (lp_syncalways(SNUM(conn)))
2310 sync_file(conn,fsp);
2312 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2313 END_PROFILE(SMBwriteunlock);
2314 return(UNIXERROR(ERRHRD,ERRdiskfull));
2318 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2319 (SMB_BIG_UINT)startpos);
2320 if (NT_STATUS_V(status)) {
2321 END_PROFILE(SMBwriteunlock);
2322 return ERROR_NT(status);
2326 outsize = set_message(outbuf,1,0,True);
2328 SSVAL(outbuf,smb_vwv0,nwritten);
2330 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2331 fsp->fnum, (int)numtowrite, (int)nwritten));
2333 END_PROFILE(SMBwriteunlock);
2337 /****************************************************************************
2339 ****************************************************************************/
2341 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2344 ssize_t nwritten = -1;
2347 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2349 START_PROFILE(SMBwrite);
2351 /* If it's an IPC, pass off the pipe handler. */
2353 END_PROFILE(SMBwrite);
2354 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2357 CHECK_FSP(fsp,conn);
2360 numtowrite = SVAL(inbuf,smb_vwv1);
2361 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2362 data = smb_buf(inbuf) + 3;
2364 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2365 END_PROFILE(SMBwrite);
2366 return ERROR_DOS(ERRDOS,ERRlock);
2370 * X/Open SMB protocol says that if smb_vwv1 is
2371 * zero then the file size should be extended or
2372 * truncated to the size given in smb_vwv[2-3].
2375 if(numtowrite == 0) {
2377 * This is actually an allocate call, and set EOF. JRA.
2379 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2381 END_PROFILE(SMBwrite);
2382 return ERROR_NT(NT_STATUS_DISK_FULL);
2384 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2386 END_PROFILE(SMBwrite);
2387 return ERROR_NT(NT_STATUS_DISK_FULL);
2390 nwritten = write_file(fsp,data,startpos,numtowrite);
2392 if (lp_syncalways(SNUM(conn)))
2393 sync_file(conn,fsp);
2395 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2396 END_PROFILE(SMBwrite);
2397 return(UNIXERROR(ERRHRD,ERRdiskfull));
2400 outsize = set_message(outbuf,1,0,True);
2402 SSVAL(outbuf,smb_vwv0,nwritten);
2404 if (nwritten < (ssize_t)numtowrite) {
2405 SCVAL(outbuf,smb_rcls,ERRHRD);
2406 SSVAL(outbuf,smb_err,ERRdiskfull);
2409 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2411 END_PROFILE(SMBwrite);
2415 /****************************************************************************
2416 Reply to a write and X.
2417 ****************************************************************************/
2419 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2421 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2422 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2423 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2424 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2425 ssize_t nwritten = -1;
2426 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2427 unsigned int smblen = smb_len(inbuf);
2429 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2430 START_PROFILE(SMBwriteX);
2432 /* If it's an IPC, pass off the pipe handler. */
2434 END_PROFILE(SMBwriteX);
2435 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2438 CHECK_FSP(fsp,conn);
2441 /* Deal with possible LARGE_WRITEX */
2443 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2445 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2446 END_PROFILE(SMBwriteX);
2447 return ERROR_DOS(ERRDOS,ERRbadmem);
2450 data = smb_base(inbuf) + smb_doff;
2452 if(CVAL(inbuf,smb_wct) == 14) {
2453 #ifdef LARGE_SMB_OFF_T
2455 * This is a large offset (64 bit) write.
2457 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2459 #else /* !LARGE_SMB_OFF_T */
2462 * Ensure we haven't been sent a >32 bit offset.
2465 if(IVAL(inbuf,smb_vwv12) != 0) {
2466 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2467 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2468 END_PROFILE(SMBwriteX);
2469 return ERROR_DOS(ERRDOS,ERRbadaccess);
2472 #endif /* LARGE_SMB_OFF_T */
2475 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2476 END_PROFILE(SMBwriteX);
2477 return ERROR_DOS(ERRDOS,ERRlock);
2480 /* X/Open SMB protocol says that, unlike SMBwrite
2481 if the length is zero then NO truncation is
2482 done, just a write of zero. To truncate a file,
2488 nwritten = write_file(fsp,data,startpos,numtowrite);
2490 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2491 END_PROFILE(SMBwriteX);
2492 return(UNIXERROR(ERRHRD,ERRdiskfull));
2495 set_message(outbuf,6,0,True);
2497 SSVAL(outbuf,smb_vwv2,nwritten);
2499 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2501 if (nwritten < (ssize_t)numtowrite) {
2502 SCVAL(outbuf,smb_rcls,ERRHRD);
2503 SSVAL(outbuf,smb_err,ERRdiskfull);
2506 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2507 fsp->fnum, (int)numtowrite, (int)nwritten));
2509 if (lp_syncalways(SNUM(conn)) || write_through)
2510 sync_file(conn,fsp);
2512 END_PROFILE(SMBwriteX);
2513 return chain_reply(inbuf,outbuf,length,bufsize);
2516 /****************************************************************************
2518 ****************************************************************************/
2520 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2526 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2527 START_PROFILE(SMBlseek);
2529 CHECK_FSP(fsp,conn);
2531 flush_write_cache(fsp, SEEK_FLUSH);
2533 mode = SVAL(inbuf,smb_vwv1) & 3;
2534 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2535 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2544 res = fsp->pos + startpos;
2555 if (umode == SEEK_END) {
2556 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2557 if(errno == EINVAL) {
2558 SMB_OFF_T current_pos = startpos;
2559 SMB_STRUCT_STAT sbuf;
2561 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2562 END_PROFILE(SMBlseek);
2563 return(UNIXERROR(ERRDOS,ERRnoaccess));
2566 current_pos += sbuf.st_size;
2568 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2573 END_PROFILE(SMBlseek);
2574 return(UNIXERROR(ERRDOS,ERRnoaccess));
2580 outsize = set_message(outbuf,2,0,True);
2581 SIVAL(outbuf,smb_vwv0,res);
2583 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2584 fsp->fnum, (double)startpos, (double)res, mode));
2586 END_PROFILE(SMBlseek);
2590 /****************************************************************************
2592 ****************************************************************************/
2594 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2596 int outsize = set_message(outbuf,0,0,True);
2597 uint16 fnum = SVAL(inbuf,smb_vwv0);
2598 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2599 START_PROFILE(SMBflush);
2602 CHECK_FSP(fsp,conn);
2605 file_sync_all(conn);
2607 sync_file(conn,fsp);
2610 DEBUG(3,("flush\n"));
2611 END_PROFILE(SMBflush);
2615 /****************************************************************************
2617 ****************************************************************************/
2619 int reply_exit(connection_struct *conn,
2620 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2623 START_PROFILE(SMBexit);
2625 file_close_pid(SVAL(inbuf,smb_pid));
2627 outsize = set_message(outbuf,0,0,True);
2629 DEBUG(3,("exit\n"));
2631 END_PROFILE(SMBexit);
2635 /****************************************************************************
2636 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2637 ****************************************************************************/
2639 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2642 extern struct current_user current_user;
2645 int32 eclass = 0, err = 0;
2646 files_struct *fsp = NULL;
2647 START_PROFILE(SMBclose);
2649 outsize = set_message(outbuf,0,0,True);
2651 /* If it's an IPC, pass off to the pipe handler. */
2653 END_PROFILE(SMBclose);
2654 return reply_pipe_close(conn, inbuf,outbuf);
2657 fsp = file_fsp(inbuf,smb_vwv0);
2660 * We can only use CHECK_FSP if we know it's not a directory.
2663 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2664 END_PROFILE(SMBclose);
2665 return ERROR_DOS(ERRDOS,ERRbadfid);
2668 if(fsp->is_directory) {
2670 * Special case - close NT SMB directory handle.
2672 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2673 close_file(fsp,True);
2676 * Close ordinary file.
2681 /* Save the name for time set in close. */
2682 pstrcpy( file_name, fsp->fsp_name);
2684 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2686 conn->num_files_open));
2689 * close_file() returns the unix errno if an error
2690 * was detected on close - normally this is due to
2691 * a disk full error. If not then it was probably an I/O error.
2694 if((close_err = close_file(fsp,True)) != 0) {
2696 END_PROFILE(SMBclose);
2697 return (UNIXERROR(ERRHRD,ERRgeneral));
2701 * Now take care of any time sent in the close.
2704 mtime = make_unix_date3(inbuf+smb_vwv1);
2706 /* try and set the date */
2707 set_filetime(conn, file_name, mtime);
2711 /* We have a cached error */
2713 END_PROFILE(SMBclose);
2714 return ERROR_DOS(eclass,err);
2717 END_PROFILE(SMBclose);
2721 /****************************************************************************
2722 Reply to a writeclose (Core+ protocol).
2723 ****************************************************************************/
2725 int reply_writeclose(connection_struct *conn,
2726 char *inbuf,char *outbuf, int size, int dum_buffsize)
2729 ssize_t nwritten = -1;
2735 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2736 START_PROFILE(SMBwriteclose);
2738 CHECK_FSP(fsp,conn);
2741 numtowrite = SVAL(inbuf,smb_vwv1);
2742 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2743 mtime = make_unix_date3(inbuf+smb_vwv4);
2744 data = smb_buf(inbuf) + 1;
2746 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2747 END_PROFILE(SMBwriteclose);
2748 return ERROR_DOS(ERRDOS,ERRlock);
2751 nwritten = write_file(fsp,data,startpos,numtowrite);
2753 set_filetime(conn, fsp->fsp_name,mtime);
2756 * More insanity. W2K only closes the file if writelen > 0.
2761 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2763 close_err = close_file(fsp,True);
2766 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2767 fsp->fnum, (int)numtowrite, (int)nwritten,
2768 conn->num_files_open));
2770 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2771 END_PROFILE(SMBwriteclose);
2772 return(UNIXERROR(ERRHRD,ERRdiskfull));
2775 if(close_err != 0) {
2777 END_PROFILE(SMBwriteclose);
2778 return(UNIXERROR(ERRHRD,ERRgeneral));
2781 outsize = set_message(outbuf,1,0,True);
2783 SSVAL(outbuf,smb_vwv0,nwritten);
2784 END_PROFILE(SMBwriteclose);
2788 /****************************************************************************
2790 ****************************************************************************/
2792 int reply_lock(connection_struct *conn,
2793 char *inbuf,char *outbuf, int length, int dum_buffsize)
2795 int outsize = set_message(outbuf,0,0,True);
2796 SMB_BIG_UINT count,offset;
2798 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2799 BOOL my_lock_ctx = False;
2801 START_PROFILE(SMBlock);
2803 CHECK_FSP(fsp,conn);
2805 release_level_2_oplocks_on_change(fsp);
2807 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2808 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2810 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2811 fsp->fd, fsp->fnum, (double)offset, (double)count));
2813 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2814 if (NT_STATUS_V(status)) {
2816 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2817 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2819 * A blocking lock was requested. Package up
2820 * this smb into a queued request and push it
2821 * onto the blocking lock queue.
2823 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2824 END_PROFILE(SMBlock);
2829 END_PROFILE(SMBlock);
2830 return ERROR_NT(status);
2833 END_PROFILE(SMBlock);
2837 /****************************************************************************
2839 ****************************************************************************/
2841 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2844 int outsize = set_message(outbuf,0,0,True);
2845 SMB_BIG_UINT count,offset;
2847 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2848 START_PROFILE(SMBunlock);
2850 CHECK_FSP(fsp,conn);
2852 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2853 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2855 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2856 if (NT_STATUS_V(status)) {
2857 END_PROFILE(SMBunlock);
2858 return ERROR_NT(status);
2861 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2862 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2864 END_PROFILE(SMBunlock);
2868 /****************************************************************************
2870 ****************************************************************************/
2872 int reply_tdis(connection_struct *conn,
2873 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2875 int outsize = set_message(outbuf,0,0,True);
2877 START_PROFILE(SMBtdis);
2879 vuid = SVAL(inbuf,smb_uid);
2882 DEBUG(4,("Invalid connection in tdis\n"));
2883 END_PROFILE(SMBtdis);
2884 return ERROR_DOS(ERRSRV,ERRinvnid);
2889 close_cnum(conn,vuid);
2891 END_PROFILE(SMBtdis);
2895 /****************************************************************************
2897 ****************************************************************************/
2899 int reply_echo(connection_struct *conn,
2900 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2902 int smb_reverb = SVAL(inbuf,smb_vwv0);
2904 unsigned int data_len = smb_buflen(inbuf);
2905 int outsize = set_message(outbuf,1,data_len,True);
2906 START_PROFILE(SMBecho);
2908 if (data_len > BUFFER_SIZE) {
2909 DEBUG(0,("reply_echo: data_len too large.\n"));
2910 END_PROFILE(SMBecho);
2914 /* copy any incoming data back out */
2916 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2918 if (smb_reverb > 100) {
2919 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2923 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2924 SSVAL(outbuf,smb_vwv0,seq_num);
2926 smb_setlen(outbuf,outsize - 4);
2928 if (!send_smb(smbd_server_fd(),outbuf))
2929 exit_server("reply_echo: send_smb failed.");
2932 DEBUG(3,("echo %d times\n", smb_reverb));
2936 END_PROFILE(SMBecho);
2940 /****************************************************************************
2941 Reply to a printopen.
2942 ****************************************************************************/
2944 int reply_printopen(connection_struct *conn,
2945 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2949 START_PROFILE(SMBsplopen);
2951 if (!CAN_PRINT(conn)) {
2952 END_PROFILE(SMBsplopen);
2953 return ERROR_DOS(ERRDOS,ERRnoaccess);
2956 /* Open for exclusive use, write only. */
2957 fsp = print_fsp_open(conn, NULL);
2960 END_PROFILE(SMBsplopen);
2961 return(UNIXERROR(ERRDOS,ERRnoaccess));
2964 outsize = set_message(outbuf,1,0,True);
2965 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2967 DEBUG(3,("openprint fd=%d fnum=%d\n",
2968 fsp->fd, fsp->fnum));
2970 END_PROFILE(SMBsplopen);
2974 /****************************************************************************
2975 Reply to a printclose.
2976 ****************************************************************************/
2978 int reply_printclose(connection_struct *conn,
2979 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2981 int outsize = set_message(outbuf,0,0,True);
2982 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2984 START_PROFILE(SMBsplclose);
2986 CHECK_FSP(fsp,conn);
2988 if (!CAN_PRINT(conn)) {
2989 END_PROFILE(SMBsplclose);
2990 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2993 DEBUG(3,("printclose fd=%d fnum=%d\n",
2994 fsp->fd,fsp->fnum));
2996 close_err = close_file(fsp,True);
2998 if(close_err != 0) {
3000 END_PROFILE(SMBsplclose);
3001 return(UNIXERROR(ERRHRD,ERRgeneral));
3004 END_PROFILE(SMBsplclose);
3008 /****************************************************************************
3009 Reply to a printqueue.
3010 ****************************************************************************/
3012 int reply_printqueue(connection_struct *conn,
3013 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3015 int outsize = set_message(outbuf,2,3,True);
3016 int max_count = SVAL(inbuf,smb_vwv0);
3017 int start_index = SVAL(inbuf,smb_vwv1);
3018 START_PROFILE(SMBsplretq);
3020 /* we used to allow the client to get the cnum wrong, but that
3021 is really quite gross and only worked when there was only
3022 one printer - I think we should now only accept it if they
3023 get it right (tridge) */
3024 if (!CAN_PRINT(conn)) {
3025 END_PROFILE(SMBsplretq);
3026 return ERROR_DOS(ERRDOS,ERRnoaccess);
3029 SSVAL(outbuf,smb_vwv0,0);
3030 SSVAL(outbuf,smb_vwv1,0);
3031 SCVAL(smb_buf(outbuf),0,1);
3032 SSVAL(smb_buf(outbuf),1,0);
3034 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3035 start_index, max_count));
3038 print_queue_struct *queue = NULL;
3039 print_status_struct status;
3040 char *p = smb_buf(outbuf) + 3;
3041 int count = print_queue_status(SNUM(conn), &queue, &status);
3042 int num_to_get = ABS(max_count);
3043 int first = (max_count>0?start_index:start_index+max_count+1);
3049 num_to_get = MIN(num_to_get,count-first);
3052 for (i=first;i<first+num_to_get;i++) {
3053 put_dos_date2(p,0,queue[i].time);
3054 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3055 SSVAL(p,5, queue[i].job);
3056 SIVAL(p,7,queue[i].size);
3058 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3063 outsize = set_message(outbuf,2,28*count+3,False);
3064 SSVAL(outbuf,smb_vwv0,count);
3065 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3066 SCVAL(smb_buf(outbuf),0,1);
3067 SSVAL(smb_buf(outbuf),1,28*count);
3072 DEBUG(3,("%d entries returned in queue\n",count));
3075 END_PROFILE(SMBsplretq);
3079 /****************************************************************************
3080 Reply to a printwrite.
3081 ****************************************************************************/
3083 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3086 int outsize = set_message(outbuf,0,0,True);
3088 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3090 START_PROFILE(SMBsplwr);
3092 if (!CAN_PRINT(conn)) {
3093 END_PROFILE(SMBsplwr);
3094 return ERROR_DOS(ERRDOS,ERRnoaccess);
3097 CHECK_FSP(fsp,conn);
3100 numtowrite = SVAL(smb_buf(inbuf),1);
3101 data = smb_buf(inbuf) + 3;
3103 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3104 END_PROFILE(SMBsplwr);
3105 return(UNIXERROR(ERRHRD,ERRdiskfull));
3108 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3110 END_PROFILE(SMBsplwr);
3114 /****************************************************************************
3115 The guts of the mkdir command, split out so it may be called by the NT SMB
3117 ****************************************************************************/
3119 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3121 BOOL bad_path = False;
3122 SMB_STRUCT_STAT sbuf;
3125 unix_convert(directory,conn,0,&bad_path,&sbuf);
3127 if( strchr_m(directory, ':')) {
3128 return NT_STATUS_NOT_A_DIRECTORY;
3131 if (ms_has_wild(directory)) {
3132 return NT_STATUS_OBJECT_NAME_INVALID;
3135 if (check_name(directory, conn))
3136 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3139 if(errno == ENOENT) {
3141 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3143 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3145 return map_nt_error_from_unix(errno);
3148 return NT_STATUS_OK;
3151 /****************************************************************************
3153 ****************************************************************************/
3155 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3160 START_PROFILE(SMBmkdir);
3162 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3163 if (!NT_STATUS_IS_OK(status)) {
3164 END_PROFILE(SMBmkdir);
3165 return ERROR_NT(status);
3168 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3170 status = mkdir_internal(conn, directory);
3171 if (!NT_STATUS_IS_OK(status)) {
3172 END_PROFILE(SMBmkdir);
3173 return ERROR_NT(status);
3176 outsize = set_message(outbuf,0,0,True);
3178 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3180 END_PROFILE(SMBmkdir);
3184 /****************************************************************************
3185 Static function used by reply_rmdir to delete an entire directory
3186 tree recursively. Return False on ok, True on fail.
3187 ****************************************************************************/
3189 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3191 const char *dname = NULL;
3193 void *dirptr = OpenDir(conn, directory, False);
3198 while((dname = ReadDirName(dirptr))) {
3202 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3205 /* Construct the full name. */
3206 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3212 pstrcpy(fullname, directory);
3213 pstrcat(fullname, "/");
3214 pstrcat(fullname, dname);
3216 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3221 if(st.st_mode & S_IFDIR) {
3222 if(recursive_rmdir(conn, fullname)!=0) {
3226 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3230 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3239 /****************************************************************************
3240 The internals of the rmdir code - called elsewhere.
3241 ****************************************************************************/
3243 BOOL rmdir_internals(connection_struct *conn, char *directory)
3247 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3248 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3250 * Check to see if the only thing in this directory are
3251 * vetoed files/directories. If so then delete them and
3252 * retry. If we fail to delete any of them (and we *don't*
3253 * do a recursive delete) then fail the rmdir.
3255 BOOL all_veto_files = True;
3257 void *dirptr = OpenDir(conn, directory, False);
3259 if(dirptr != NULL) {
3260 int dirpos = TellDir(dirptr);
3261 while ((dname = ReadDirName(dirptr))) {
3262 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3264 if(!IS_VETO_PATH(conn, dname)) {
3265 all_veto_files = False;
3270 if(all_veto_files) {
3271 SeekDir(dirptr,dirpos);
3272 while ((dname = ReadDirName(dirptr))) {
3276 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3279 /* Construct the full name. */
3280 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3285 pstrcpy(fullname, directory);
3286 pstrcat(fullname, "/");
3287 pstrcat(fullname, dname);
3289 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3291 if(st.st_mode & S_IFDIR) {
3292 if(lp_recursive_veto_delete(SNUM(conn))) {
3293 if(recursive_rmdir(conn, fullname) != 0)
3296 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3298 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3302 /* Retry the rmdir */
3303 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3313 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3318 /****************************************************************************
3320 ****************************************************************************/
3322 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3327 BOOL bad_path = False;
3328 SMB_STRUCT_STAT sbuf;
3330 START_PROFILE(SMBrmdir);
3332 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3333 if (!NT_STATUS_IS_OK(status)) {
3334 END_PROFILE(SMBrmdir);
3335 return ERROR_NT(status);
3338 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3340 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3342 if (check_name(directory,conn)) {
3343 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3344 ok = rmdir_internals(conn, directory);
3348 END_PROFILE(SMBrmdir);
3349 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3352 outsize = set_message(outbuf,0,0,True);
3354 DEBUG( 3, ( "rmdir %s\n", directory ) );
3356 END_PROFILE(SMBrmdir);
3360 /*******************************************************************
3361 Resolve wildcards in a filename rename.
3362 ********************************************************************/
3364 static BOOL resolve_wildcards(const char *name1, char *name2)
3366 fstring root1,root2;
3368 char *p,*p2, *pname1, *pname2;
3369 int available_space;
3372 pname1 = strrchr_m(name1,'/');
3373 pname2 = strrchr_m(name2,'/');
3375 if (!pname1 || !pname2)
3378 fstrcpy(root1,pname1);
3379 fstrcpy(root2,pname2);
3380 p = strrchr_m(root1,'.');
3387 p = strrchr_m(root2,'.');
3421 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3424 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3426 pstrcpy_base(pname2, root2, name2);
3432 /****************************************************************************
3433 Ensure open files have their names updates.
3434 ****************************************************************************/
3436 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3439 BOOL did_rename = False;
3441 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3442 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3443 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3444 fsp->fsp_name, newname ));
3445 string_set(&fsp->fsp_name, newname);
3450 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3451 (unsigned int)dev, (double)inode, newname ));
3454 /****************************************************************************
3455 Rename an open file - given an fsp.
3456 ****************************************************************************/
3458 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3460 SMB_STRUCT_STAT sbuf;
3461 BOOL bad_path = False;
3462 pstring newname_last_component;
3463 NTSTATUS error = NT_STATUS_OK;
3468 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3470 /* Quick check for "." and ".." */
3471 if (!bad_path && newname_last_component[0] == '.') {
3472 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3473 return NT_STATUS_ACCESS_DENIED;
3476 if (!rcdest && bad_path) {
3477 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3480 /* Ensure newname contains a '/' */
3481 if(strrchr_m(newname,'/') == 0) {
3484 pstrcpy(tmpstr, "./");
3485 pstrcat(tmpstr, newname);
3486 pstrcpy(newname, tmpstr);
3490 * Check for special case with case preserving and not
3491 * case sensitive. If the old last component differs from the original
3492 * last component only by case, then we should allow
3493 * the rename (user is trying to change the case of the
3497 if((case_sensitive == False) && (case_preserve == True) &&
3498 strequal(newname, fsp->fsp_name)) {
3500 pstring newname_modified_last_component;
3503 * Get the last component of the modified name.
3504 * Note that we guarantee that newname contains a '/'
3507 p = strrchr_m(newname,'/');
3508 pstrcpy(newname_modified_last_component,p+1);
3510 if(strcsequal(newname_modified_last_component,
3511 newname_last_component) == False) {
3513 * Replace the modified last component with
3516 pstrcpy(p+1, newname_last_component);
3521 * If the src and dest names are identical - including case,
3522 * don't do the rename, just return success.
3525 if (strcsequal(fsp->fsp_name, newname)) {
3526 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3528 return NT_STATUS_OK;
3531 dest_exists = vfs_object_exist(conn,newname,NULL);
3533 if(!replace_if_exists && dest_exists) {
3534 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3535 fsp->fsp_name,newname));
3536 return NT_STATUS_OBJECT_NAME_COLLISION;
3539 error = can_rename(newname,conn,&sbuf);
3541 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3542 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3543 nt_errstr(error), fsp->fsp_name,newname));
3544 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3545 error = NT_STATUS_ACCESS_DENIED;
3549 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3550 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3551 fsp->fsp_name,newname));
3552 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3553 return NT_STATUS_OK;
3556 if (errno == ENOTDIR || errno == EISDIR)
3557 error = NT_STATUS_OBJECT_NAME_COLLISION;
3559 error = map_nt_error_from_unix(errno);
3561 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3562 nt_errstr(error), fsp->fsp_name,newname));
3567 /****************************************************************************
3568 The guts of the rename command, split out so it may be called by the NT SMB
3570 ****************************************************************************/
3572 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3576 pstring last_component_src;
3577 pstring last_component_dest;
3580 BOOL bad_path_src = False;
3581 BOOL bad_path_dest = False;
3583 NTSTATUS error = NT_STATUS_OK;
3586 SMB_STRUCT_STAT sbuf1, sbuf2;
3588 *directory = *mask = 0;
3593 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3594 if (!rc && bad_path_src) {
3595 if (ms_has_wild(last_component_src))
3596 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3597 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3600 /* Quick check for "." and ".." */
3601 if (last_component_src[0] == '.') {
3602 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3603 return NT_STATUS_OBJECT_NAME_INVALID;
3607 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3609 /* Quick check for "." and ".." */
3610 if (last_component_dest[0] == '.') {
3611 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3612 return NT_STATUS_OBJECT_NAME_INVALID;
3617 * Split the old name into directory and last component
3618 * strings. Note that unix_convert may have stripped off a
3619 * leading ./ from both name and newname if the rename is
3620 * at the root of the share. We need to make sure either both
3621 * name and newname contain a / character or neither of them do
3622 * as this is checked in resolve_wildcards().
3625 p = strrchr_m(name,'/');
3627 pstrcpy(directory,".");
3631 pstrcpy(directory,name);
3633 *p = '/'; /* Replace needed for exceptional test below. */
3637 * We should only check the mangled cache
3638 * here if unix_convert failed. This means
3639 * that the path in 'mask' doesn't exist
3640 * on the file system and so we need to look
3641 * for a possible mangle. This patch from
3642 * Tine Smukavec <valentin.smukavec@hermes.si>.
3645 if (!rc && mangle_is_mangled(mask))
3646 mangle_check_cache( mask );
3648 has_wild = ms_has_wild(mask);
3652 * No wildcards - just process the one file.
3654 BOOL is_short_name = mangle_is_8_3(name, True);
3656 /* Add a terminating '/' to the directory name. */
3657 pstrcat(directory,"/");
3658 pstrcat(directory,mask);
3660 /* Ensure newname contains a '/' also */
3661 if(strrchr_m(newname,'/') == 0) {
3664 pstrcpy(tmpstr, "./");
3665 pstrcat(tmpstr, newname);
3666 pstrcpy(newname, tmpstr);
3669 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3670 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3671 case_sensitive, case_preserve, short_case_preserve, directory,
3672 newname, last_component_dest, is_short_name));
3675 * Check for special case with case preserving and not
3676 * case sensitive, if directory and newname are identical,
3677 * and the old last component differs from the original
3678 * last component only by case, then we should allow
3679 * the rename (user is trying to change the case of the
3682 if((case_sensitive == False) &&
3683 (((case_preserve == True) &&
3684 (is_short_name == False)) ||
3685 ((short_case_preserve == True) &&
3686 (is_short_name == True))) &&
3687 strcsequal(directory, newname)) {
3688 pstring modified_last_component;
3691 * Get the last component of the modified name.
3692 * Note that we guarantee that newname contains a '/'
3695 p = strrchr_m(newname,'/');
3696 pstrcpy(modified_last_component,p+1);
3698 if(strcsequal(modified_last_component,
3699 last_component_dest) == False) {
3701 * Replace the modified last component with
3704 pstrcpy(p+1, last_component_dest);
3708 resolve_wildcards(directory,newname);
3711 * The source object must exist.
3714 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3715 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3716 directory,newname));
3718 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3720 * Must return different errors depending on whether the parent
3721 * directory existed or not.
3724 p = strrchr_m(directory, '/');
3726 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3728 if (vfs_object_exist(conn, directory, NULL))
3729 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3730 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3732 error = map_nt_error_from_unix(errno);
3733 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3734 nt_errstr(error), directory,newname));
3739 if (!rcdest && bad_path_dest) {
3740 if (ms_has_wild(last_component_dest))
3741 return NT_STATUS_OBJECT_NAME_INVALID;
3742 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3745 error = can_rename(directory,conn,&sbuf1);
3747 if (!NT_STATUS_IS_OK(error)) {
3748 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3749 nt_errstr(error), directory,newname));
3754 * If the src and dest names are identical - including case,
3755 * don't do the rename, just return success.
3758 if (strcsequal(directory, newname)) {
3759 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3760 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3761 return NT_STATUS_OK;
3764 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3765 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3766 directory,newname));
3767 return NT_STATUS_OBJECT_NAME_COLLISION;
3770 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3771 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3772 directory,newname));
3773 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3774 return NT_STATUS_OK;
3777 if (errno == ENOTDIR || errno == EISDIR)
3778 error = NT_STATUS_OBJECT_NAME_COLLISION;
3780 error = map_nt_error_from_unix(errno);
3782 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3783 nt_errstr(error), directory,newname));
3788 * Wildcards - process each file that matches.
3790 void *dirptr = NULL;
3794 if (check_name(directory,conn))
3795 dirptr = OpenDir(conn, directory, True);
3798 error = NT_STATUS_NO_SUCH_FILE;
3799 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3801 if (strequal(mask,"????????.???"))
3804 while ((dname = ReadDirName(dirptr))) {
3806 BOOL sysdir_entry = False;
3808 pstrcpy(fname,dname);
3810 /* Quick check for "." and ".." */
3811 if (fname[0] == '.') {
3812 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3814 sysdir_entry = True;
3821 if(!mask_match(fname, mask, case_sensitive))
3825 error = NT_STATUS_OBJECT_NAME_INVALID;
3829 error = NT_STATUS_ACCESS_DENIED;
3830 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3831 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3832 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3833 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3836 error = can_rename(fname,conn,&sbuf1);
3837 if (!NT_STATUS_IS_OK(error)) {
3838 DEBUG(6,("rename %s refused\n", fname));
3841 pstrcpy(destname,newname);
3843 if (!resolve_wildcards(fname,destname)) {
3844 DEBUG(6,("resolve_wildcards %s %s failed\n",
3849 if (!replace_if_exists &&
3850 vfs_file_exist(conn,destname, NULL)) {
3851 DEBUG(6,("file_exist %s\n", destname));
3852 error = NT_STATUS_OBJECT_NAME_COLLISION;
3856 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3857 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3859 error = NT_STATUS_OK;
3861 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3866 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3867 if (!rcdest && bad_path_dest) {
3868 if (ms_has_wild(last_component_dest))
3869 return NT_STATUS_OBJECT_NAME_INVALID;
3870 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3875 if (count == 0 && NT_STATUS_IS_OK(error)) {
3876 error = map_nt_error_from_unix(errno);
3882 /****************************************************************************
3884 ****************************************************************************/
3886 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3893 uint16 attrs = SVAL(inbuf,smb_vwv0);
3896 START_PROFILE(SMBmv);
3898 p = smb_buf(inbuf) + 1;
3899 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
3900 if (!NT_STATUS_IS_OK(status)) {
3902 return ERROR_NT(status);
3905 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
3906 if (!NT_STATUS_IS_OK(status)) {
3908 return ERROR_NT(status);
3911 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3912 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3914 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3916 status = rename_internals(conn, name, newname, attrs, False);
3917 if (!NT_STATUS_IS_OK(status)) {
3919 return ERROR_NT(status);
3923 * Win2k needs a changenotify request response before it will
3924 * update after a rename..
3926 process_pending_change_notify_queue((time_t)0);
3927 outsize = set_message(outbuf,0,0,True);
3933 /*******************************************************************
3934 Copy a file as part of a reply_copy.
3935 ******************************************************************/
3937 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3938 int count,BOOL target_is_directory, int *err_ret)
3941 SMB_STRUCT_STAT src_sbuf, sbuf2;
3943 files_struct *fsp1,*fsp2;
3948 pstrcpy(dest,dest1);
3949 if (target_is_directory) {
3950 char *p = strrchr_m(src,'/');
3959 if (!vfs_file_exist(conn,src,&src_sbuf))
3962 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3963 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3968 if (!target_is_directory && count)
3969 ofun = FILE_EXISTS_OPEN;
3971 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3972 ZERO_STRUCTP(&sbuf2);
3974 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3975 ofun,src_sbuf.st_mode,0,&Access,&action);
3978 close_file(fsp1,False);
3982 if ((ofun&3) == 1) {
3983 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3984 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3986 * Stop the copy from occurring.
3989 src_sbuf.st_size = 0;
3993 if (src_sbuf.st_size)
3994 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3996 close_file(fsp1,False);
3998 /* Ensure the modtime is set correctly on the destination file. */
3999 fsp2->pending_modtime = src_sbuf.st_mtime;
4002 * As we are opening fsp1 read-only we only expect
4003 * an error on close on fsp2 if we are out of space.
4004 * Thus we don't look at the error return from the
4007 *err_ret = close_file(fsp2,False);
4009 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4012 /****************************************************************************
4013 Reply to a file copy.
4014 ****************************************************************************/
4016 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4021 pstring mask,newname;
4024 int error = ERRnoaccess;
4028 int tid2 = SVAL(inbuf,smb_vwv0);
4029 int ofun = SVAL(inbuf,smb_vwv1);
4030 int flags = SVAL(inbuf,smb_vwv2);
4031 BOOL target_is_directory=False;
4032 BOOL bad_path1 = False;
4033 BOOL bad_path2 = False;
4035 SMB_STRUCT_STAT sbuf1, sbuf2;
4038 START_PROFILE(SMBcopy);
4040 *directory = *mask = 0;
4043 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
4044 if (!NT_STATUS_IS_OK(status)) {
4045 END_PROFILE(SMBcopy);
4046 return ERROR_NT(status);
4048 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4049 if (!NT_STATUS_IS_OK(status)) {
4050 END_PROFILE(SMBcopy);
4051 return ERROR_NT(status);
4054 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4056 if (tid2 != conn->cnum) {
4057 /* can't currently handle inter share copies XXXX */
4058 DEBUG(3,("Rejecting inter-share copy\n"));
4059 END_PROFILE(SMBcopy);
4060 return ERROR_DOS(ERRSRV,ERRinvdevice);
4063 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4064 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4066 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4067 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4069 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4071 if ((flags&1) && target_is_directory) {
4072 END_PROFILE(SMBcopy);
4073 return ERROR_DOS(ERRDOS,ERRbadfile);
4076 if ((flags&2) && !target_is_directory) {
4077 END_PROFILE(SMBcopy);
4078 return ERROR_DOS(ERRDOS,ERRbadpath);
4081 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4082 /* wants a tree copy! XXXX */
4083 DEBUG(3,("Rejecting tree copy\n"));
4084 END_PROFILE(SMBcopy);
4085 return ERROR_DOS(ERRSRV,ERRerror);
4088 p = strrchr_m(name,'/');
4090 pstrcpy(directory,"./");
4094 pstrcpy(directory,name);
4099 * We should only check the mangled cache
4100 * here if unix_convert failed. This means
4101 * that the path in 'mask' doesn't exist
4102 * on the file system and so we need to look
4103 * for a possible mangle. This patch from
4104 * Tine Smukavec <valentin.smukavec@hermes.si>.
4107 if (!rc && mangle_is_mangled(mask))
4108 mangle_check_cache( mask );
4110 has_wild = ms_has_wild(mask);
4113 pstrcat(directory,"/");
4114 pstrcat(directory,mask);
4115 if (resolve_wildcards(directory,newname) &&
4116 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4120 END_PROFILE(SMBcopy);
4121 return(UNIXERROR(ERRHRD,ERRgeneral));
4124 exists = vfs_file_exist(conn,directory,NULL);
4127 void *dirptr = NULL;
4131 if (check_name(directory,conn))
4132 dirptr = OpenDir(conn, directory, True);
4137 if (strequal(mask,"????????.???"))
4140 while ((dname = ReadDirName(dirptr))) {
4142 pstrcpy(fname,dname);
4144 if(!mask_match(fname, mask, case_sensitive))
4147 error = ERRnoaccess;
4148 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4149 pstrcpy(destname,newname);
4150 if (resolve_wildcards(fname,destname) &&
4151 copy_file(fname,destname,conn,ofun,
4152 count,target_is_directory,&err))
4154 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4162 /* Error on close... */
4164 END_PROFILE(SMBcopy);
4165 return(UNIXERROR(ERRHRD,ERRgeneral));
4169 END_PROFILE(SMBcopy);
4170 return ERROR_DOS(ERRDOS,error);
4172 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4173 unix_ERR_class = ERRDOS;
4174 unix_ERR_code = ERRbadpath;
4176 END_PROFILE(SMBcopy);
4177 return(UNIXERROR(ERRDOS,error));
4181 outsize = set_message(outbuf,1,0,True);
4182 SSVAL(outbuf,smb_vwv0,count);
4184 END_PROFILE(SMBcopy);
4188 /****************************************************************************
4190 ****************************************************************************/
4192 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4200 START_PROFILE(pathworks_setdir);
4203 if (!CAN_SETDIR(snum)) {
4204 END_PROFILE(pathworks_setdir);
4205 return ERROR_DOS(ERRDOS,ERRnoaccess);
4208 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4209 if (!NT_STATUS_IS_OK(status)) {
4210 END_PROFILE(pathworks_setdir);
4211 return ERROR_NT(status);
4214 if (strlen(newdir) == 0) {
4217 ok = vfs_directory_exist(conn,newdir,NULL);
4219 string_set(&conn->connectpath,newdir);
4223 END_PROFILE(pathworks_setdir);
4224 return ERROR_DOS(ERRDOS,ERRbadpath);
4227 outsize = set_message(outbuf,0,0,True);
4228 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4230 DEBUG(3,("setdir %s\n", newdir));
4232 END_PROFILE(pathworks_setdir);
4236 /****************************************************************************
4237 Get a lock pid, dealing with large count requests.
4238 ****************************************************************************/
4240 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4242 if(!large_file_format)
4243 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4245 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4248 /****************************************************************************
4249 Get a lock count, dealing with large count requests.
4250 ****************************************************************************/
4252 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4254 SMB_BIG_UINT count = 0;
4256 if(!large_file_format) {
4257 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4260 #if defined(HAVE_LONGLONG)
4261 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4262 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4263 #else /* HAVE_LONGLONG */
4266 * NT4.x seems to be broken in that it sends large file (64 bit)
4267 * lockingX calls even if the CAP_LARGE_FILES was *not*
4268 * negotiated. For boxes without large unsigned ints truncate the
4269 * lock count by dropping the top 32 bits.
4272 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4273 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4274 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4275 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4276 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4279 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4280 #endif /* HAVE_LONGLONG */
4286 #if !defined(HAVE_LONGLONG)
4287 /****************************************************************************
4288 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4289 ****************************************************************************/
4291 static uint32 map_lock_offset(uint32 high, uint32 low)
4295 uint32 highcopy = high;
4298 * Try and find out how many significant bits there are in high.
4301 for(i = 0; highcopy; i++)
4305 * We use 31 bits not 32 here as POSIX
4306 * lock offsets may not be negative.
4309 mask = (~0) << (31 - i);
4312 return 0; /* Fail. */
4318 #endif /* !defined(HAVE_LONGLONG) */
4320 /****************************************************************************
4321 Get a lock offset, dealing with large offset requests.
4322 ****************************************************************************/
4324 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4326 SMB_BIG_UINT offset = 0;
4330 if(!large_file_format) {
4331 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4334 #if defined(HAVE_LONGLONG)
4335 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4336 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4337 #else /* HAVE_LONGLONG */
4340 * NT4.x seems to be broken in that it sends large file (64 bit)
4341 * lockingX calls even if the CAP_LARGE_FILES was *not*
4342 * negotiated. For boxes without large unsigned ints mangle the
4343 * lock offset by mapping the top 32 bits onto the lower 32.
4346 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4347 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4348 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4351 if((new_low = map_lock_offset(high, low)) == 0) {
4353 return (SMB_BIG_UINT)-1;
4356 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4357 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4358 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4359 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4362 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4363 #endif /* HAVE_LONGLONG */
4369 /****************************************************************************
4370 Reply to a lockingX request.
4371 ****************************************************************************/
4373 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4375 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4376 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4377 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4378 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4379 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4380 SMB_BIG_UINT count = 0, offset = 0;
4382 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4385 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4387 BOOL my_lock_ctx = False;
4390 START_PROFILE(SMBlockingX);
4392 CHECK_FSP(fsp,conn);
4394 data = smb_buf(inbuf);
4396 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4397 /* we don't support these - and CANCEL_LOCK makes w2k
4398 and XP reboot so I don't really want to be
4399 compatible! (tridge) */
4400 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4403 /* Check if this is an oplock break on a file
4404 we have granted an oplock on.
4406 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4407 /* Client can insist on breaking to none. */
4408 BOOL break_to_none = (oplocklevel == 0);
4410 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4411 (unsigned int)oplocklevel, fsp->fnum ));
4414 * Make sure we have granted an exclusive or batch oplock on this file.
4417 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4418 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4419 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4421 /* if this is a pure oplock break request then don't send a reply */
4422 if (num_locks == 0 && num_ulocks == 0) {
4423 END_PROFILE(SMBlockingX);
4426 END_PROFILE(SMBlockingX);
4427 return ERROR_DOS(ERRDOS,ERRlock);
4431 if (remove_oplock(fsp, break_to_none) == False) {
4432 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4436 /* if this is a pure oplock break request then don't send a reply */
4437 if (num_locks == 0 && num_ulocks == 0) {
4438 /* Sanity check - ensure a pure oplock break is not a
4440 if(CVAL(inbuf,smb_vwv0) != 0xff)
4441 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4442 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4443 END_PROFILE(SMBlockingX);
4449 * We do this check *after* we have checked this is not a oplock break
4450 * response message. JRA.
4453 release_level_2_oplocks_on_change(fsp);
4455 /* Data now points at the beginning of the list
4456 of smb_unlkrng structs */
4457 for(i = 0; i < (int)num_ulocks; i++) {
4458 lock_pid = get_lock_pid( data, i, large_file_format);
4459 count = get_lock_count( data, i, large_file_format);
4460 offset = get_lock_offset( data, i, large_file_format, &err);
4463 * There is no error code marked "stupid client bug".... :-).
4466 END_PROFILE(SMBlockingX);
4467 return ERROR_DOS(ERRDOS,ERRnoaccess);
4470 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4471 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4473 status = do_unlock(fsp,conn,lock_pid,count,offset);
4474 if (NT_STATUS_V(status)) {
4475 END_PROFILE(SMBlockingX);
4476 return ERROR_NT(status);
4480 /* Setup the timeout in seconds. */
4482 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4484 /* Now do any requested locks */
4485 data += ((large_file_format ? 20 : 10)*num_ulocks);
4487 /* Data now points at the beginning of the list
4488 of smb_lkrng structs */
4490 for(i = 0; i < (int)num_locks; i++) {
4491 lock_pid = get_lock_pid( data, i, large_file_format);
4492 count = get_lock_count( data, i, large_file_format);
4493 offset = get_lock_offset( data, i, large_file_format, &err);
4496 * There is no error code marked "stupid client bug".... :-).
4499 END_PROFILE(SMBlockingX);
4500 return ERROR_DOS(ERRDOS,ERRnoaccess);
4503 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4504 (double)offset, (double)count, (unsigned int)lock_pid,
4505 fsp->fsp_name, (int)lock_timeout ));
4507 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4508 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4509 if (NT_STATUS_V(status)) {
4511 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4512 * Even if it's our own lock context, we need to wait here as
4513 * there may be an unlock on the way.
4514 * So I removed a "&& !my_lock_ctx" from the following
4515 * if statement. JRA.
4517 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4519 * A blocking lock was requested. Package up
4520 * this smb into a queued request and push it
4521 * onto the blocking lock queue.
4523 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4524 END_PROFILE(SMBlockingX);
4532 /* If any of the above locks failed, then we must unlock
4533 all of the previous locks (X/Open spec). */
4534 if (i != num_locks && num_locks != 0) {
4536 * Ensure we don't do a remove on the lock that just failed,
4537 * as under POSIX rules, if we have a lock already there, we
4538 * will delete it (and we shouldn't) .....
4540 for(i--; i >= 0; i--) {
4541 lock_pid = get_lock_pid( data, i, large_file_format);
4542 count = get_lock_count( data, i, large_file_format);
4543 offset = get_lock_offset( data, i, large_file_format, &err);
4546 * There is no error code marked "stupid client bug".... :-).
4549 END_PROFILE(SMBlockingX);
4550 return ERROR_DOS(ERRDOS,ERRnoaccess);
4553 do_unlock(fsp,conn,lock_pid,count,offset);
4555 END_PROFILE(SMBlockingX);
4556 return ERROR_NT(status);
4559 set_message(outbuf,2,0,True);
4561 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4562 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4564 END_PROFILE(SMBlockingX);
4565 return chain_reply(inbuf,outbuf,length,bufsize);
4568 /****************************************************************************
4569 Reply to a SMBreadbmpx (read block multiplex) request.
4570 ****************************************************************************/
4572 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4583 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4584 START_PROFILE(SMBreadBmpx);
4586 /* this function doesn't seem to work - disable by default */
4587 if (!lp_readbmpx()) {
4588 END_PROFILE(SMBreadBmpx);
4589 return ERROR_DOS(ERRSRV,ERRuseSTD);
4592 outsize = set_message(outbuf,8,0,True);
4594 CHECK_FSP(fsp,conn);
4597 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4598 maxcount = SVAL(inbuf,smb_vwv3);
4600 data = smb_buf(outbuf);
4601 pad = ((long)data)%4;
4606 max_per_packet = bufsize-(outsize+pad);
4610 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4611 END_PROFILE(SMBreadBmpx);
4612 return ERROR_DOS(ERRDOS,ERRlock);
4616 size_t N = MIN(max_per_packet,tcount-total_read);
4618 nread = read_file(fsp,data,startpos,N);
4623 if (nread < (ssize_t)N)
4624 tcount = total_read + nread;
4626 set_message(outbuf,8,nread,False);
4627 SIVAL(outbuf,smb_vwv0,startpos);
4628 SSVAL(outbuf,smb_vwv2,tcount);
4629 SSVAL(outbuf,smb_vwv6,nread);
4630 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4632 if (!send_smb(smbd_server_fd(),outbuf))
4633 exit_server("reply_readbmpx: send_smb failed.");
4635 total_read += nread;
4637 } while (total_read < (ssize_t)tcount);
4639 END_PROFILE(SMBreadBmpx);
4643 /****************************************************************************
4644 Reply to a SMBsetattrE.
4645 ****************************************************************************/
4647 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4649 struct utimbuf unix_times;
4651 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4652 START_PROFILE(SMBsetattrE);
4654 outsize = set_message(outbuf,0,0,True);
4656 if(!fsp || (fsp->conn != conn)) {
4657 END_PROFILE(SMBgetattrE);
4658 return ERROR_DOS(ERRDOS,ERRbadfid);
4662 * Convert the DOS times into unix times. Ignore create
4663 * time as UNIX can't set this.
4666 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4667 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4670 * Patch from Ray Frush <frush@engr.colostate.edu>
4671 * Sometimes times are sent as zero - ignore them.
4674 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4675 /* Ignore request */
4676 if( DEBUGLVL( 3 ) ) {
4677 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4678 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4680 END_PROFILE(SMBsetattrE);
4682 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4683 /* set modify time = to access time if modify time was 0 */
4684 unix_times.modtime = unix_times.actime;
4687 /* Set the date on this file */
4688 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4689 END_PROFILE(SMBsetattrE);
4690 return ERROR_DOS(ERRDOS,ERRnoaccess);
4693 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4694 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4696 END_PROFILE(SMBsetattrE);
4701 /* Back from the dead for OS/2..... JRA. */
4703 /****************************************************************************
4704 Reply to a SMBwritebmpx (write block multiplex primary) request.
4705 ****************************************************************************/
4707 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4710 ssize_t nwritten = -1;
4717 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4718 START_PROFILE(SMBwriteBmpx);
4720 CHECK_FSP(fsp,conn);
4724 tcount = SVAL(inbuf,smb_vwv1);
4725 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4726 write_through = BITSETW(inbuf+smb_vwv7,0);
4727 numtowrite = SVAL(inbuf,smb_vwv10);
4728 smb_doff = SVAL(inbuf,smb_vwv11);
4730 data = smb_base(inbuf) + smb_doff;
4732 /* If this fails we need to send an SMBwriteC response,
4733 not an SMBwritebmpx - set this up now so we don't forget */
4734 SCVAL(outbuf,smb_com,SMBwritec);
4736 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4737 END_PROFILE(SMBwriteBmpx);
4738 return(ERROR_DOS(ERRDOS,ERRlock));
4741 nwritten = write_file(fsp,data,startpos,numtowrite);
4743 if(lp_syncalways(SNUM(conn)) || write_through)
4744 sync_file(conn,fsp);
4746 if(nwritten < (ssize_t)numtowrite) {
4747 END_PROFILE(SMBwriteBmpx);
4748 return(UNIXERROR(ERRHRD,ERRdiskfull));
4751 /* If the maximum to be written to this file
4752 is greater than what we just wrote then set
4753 up a secondary struct to be attached to this
4754 fd, we will use this to cache error messages etc. */
4756 if((ssize_t)tcount > nwritten) {
4757 write_bmpx_struct *wbms;
4758 if(fsp->wbmpx_ptr != NULL)
4759 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4761 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4763 DEBUG(0,("Out of memory in reply_readmpx\n"));
4764 END_PROFILE(SMBwriteBmpx);
4765 return(ERROR_DOS(ERRSRV,ERRnoresource));
4767 wbms->wr_mode = write_through;
4768 wbms->wr_discard = False; /* No errors yet */
4769 wbms->wr_total_written = nwritten;
4770 wbms->wr_errclass = 0;
4772 fsp->wbmpx_ptr = wbms;
4775 /* We are returning successfully, set the message type back to
4777 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4779 outsize = set_message(outbuf,1,0,True);
4781 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4783 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4784 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4786 if (write_through && tcount==nwritten) {
4787 /* We need to send both a primary and a secondary response */
4788 smb_setlen(outbuf,outsize - 4);
4789 if (!send_smb(smbd_server_fd(),outbuf))
4790 exit_server("reply_writebmpx: send_smb failed.");
4792 /* Now the secondary */
4793 outsize = set_message(outbuf,1,0,True);
4794 SCVAL(outbuf,smb_com,SMBwritec);
4795 SSVAL(outbuf,smb_vwv0,nwritten);
4798 END_PROFILE(SMBwriteBmpx);
4802 /****************************************************************************
4803 Reply to a SMBwritebs (write block multiplex secondary) request.
4804 ****************************************************************************/
4806 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4809 ssize_t nwritten = -1;
4816 write_bmpx_struct *wbms;
4817 BOOL send_response = False;
4818 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4819 START_PROFILE(SMBwriteBs);
4821 CHECK_FSP(fsp,conn);
4824 tcount = SVAL(inbuf,smb_vwv1);
4825 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4826 numtowrite = SVAL(inbuf,smb_vwv6);
4827 smb_doff = SVAL(inbuf,smb_vwv7);
4829 data = smb_base(inbuf) + smb_doff;
4831 /* We need to send an SMBwriteC response, not an SMBwritebs */
4832 SCVAL(outbuf,smb_com,SMBwritec);
4834 /* This fd should have an auxiliary struct attached,
4835 check that it does */
4836 wbms = fsp->wbmpx_ptr;
4838 END_PROFILE(SMBwriteBs);
4842 /* If write through is set we can return errors, else we must cache them */
4843 write_through = wbms->wr_mode;
4845 /* Check for an earlier error */
4846 if(wbms->wr_discard) {
4847 END_PROFILE(SMBwriteBs);
4848 return -1; /* Just discard the packet */
4851 nwritten = write_file(fsp,data,startpos,numtowrite);
4853 if(lp_syncalways(SNUM(conn)) || write_through)
4854 sync_file(conn,fsp);
4856 if (nwritten < (ssize_t)numtowrite) {
4858 /* We are returning an error - we can delete the aux struct */
4861 fsp->wbmpx_ptr = NULL;
4862 END_PROFILE(SMBwriteBs);
4863 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4865 END_PROFILE(SMBwriteBs);
4866 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4869 /* Increment the total written, if this matches tcount
4870 we can discard the auxiliary struct (hurrah !) and return a writeC */
4871 wbms->wr_total_written += nwritten;
4872 if(wbms->wr_total_written >= tcount) {
4873 if (write_through) {
4874 outsize = set_message(outbuf,1,0,True);
4875 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4876 send_response = True;
4880 fsp->wbmpx_ptr = NULL;
4884 END_PROFILE(SMBwriteBs);
4888 END_PROFILE(SMBwriteBs);
4892 /****************************************************************************
4893 Reply to a SMBgetattrE.
4894 ****************************************************************************/
4896 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4898 SMB_STRUCT_STAT sbuf;
4901 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4902 START_PROFILE(SMBgetattrE);
4904 outsize = set_message(outbuf,11,0,True);
4906 if(!fsp || (fsp->conn != conn)) {
4907 END_PROFILE(SMBgetattrE);
4908 return ERROR_DOS(ERRDOS,ERRbadfid);
4911 /* Do an fstat on this file */
4912 if(fsp_stat(fsp, &sbuf)) {
4913 END_PROFILE(SMBgetattrE);
4914 return(UNIXERROR(ERRDOS,ERRnoaccess));
4917 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4920 * Convert the times into dos times. Set create
4921 * date to be last modify date as UNIX doesn't save
4925 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4926 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4927 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4930 SIVAL(outbuf,smb_vwv6,0);
4931 SIVAL(outbuf,smb_vwv8,0);
4933 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4934 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4935 SIVAL(outbuf,smb_vwv8,allocation_size);
4937 SSVAL(outbuf,smb_vwv10, mode);
4939 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4941 END_PROFILE(SMBgetattrE);