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 Reply to an special message.
43 ****************************************************************************/
45 int reply_special(char *inbuf,char *outbuf)
48 int msg_type = CVAL(inbuf,0);
49 int msg_flags = CVAL(inbuf,1);
55 static BOOL already_got_session = False;
59 memset(outbuf,'\0',smb_size);
64 case 0x81: /* session request */
66 if (already_got_session) {
67 exit_server("multiple session request not permitted");
72 if (name_len(inbuf+4) > 50 ||
73 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
74 DEBUG(0,("Invalid name length in session request\n"));
77 name_extract(inbuf,4,name1);
78 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
79 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
86 name_type = name2[15];
90 set_local_machine_name(name1, True);
91 set_remote_machine_name(name2, True);
93 DEBUG(2,("netbios connect: local=%s remote=%s\n",
94 get_local_machine_name(), get_remote_machine_name() ));
96 if (name_type == 'R') {
97 /* We are being asked for a pathworks session ---
99 SCVAL(outbuf, 0,0x83);
103 /* only add the client's machine name to the list
104 of possibly valid usernames if we are operating
105 in share mode security */
106 if (lp_security() == SEC_SHARE) {
107 add_session_user(get_remote_machine_name());
110 reload_services(True);
113 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
115 already_got_session = True;
118 case 0x89: /* session keepalive request
119 (some old clients produce this?) */
120 SCVAL(outbuf,0,SMBkeepalive);
124 case 0x82: /* positive session response */
125 case 0x83: /* negative session response */
126 case 0x84: /* retarget session response */
127 DEBUG(0,("Unexpected session response\n"));
130 case SMBkeepalive: /* session keepalive */
135 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
136 msg_type, msg_flags));
141 /****************************************************************************
143 ****************************************************************************/
145 int reply_tcon(connection_struct *conn,
146 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
153 uint16 vuid = SVAL(inbuf,smb_uid);
157 DATA_BLOB password_blob;
159 START_PROFILE(SMBtcon);
161 *service_buf = *password = *dev = 0;
163 p = smb_buf(inbuf)+1;
164 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
165 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
167 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
169 p = strrchr_m(service_buf,'\\');
173 service = service_buf;
176 password_blob = data_blob(password, pwlen+1);
178 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
180 data_blob_clear_free(&password_blob);
183 END_PROFILE(SMBtcon);
184 return ERROR_NT(nt_status);
187 outsize = set_message(outbuf,2,0,True);
188 SSVAL(outbuf,smb_vwv0,max_recv);
189 SSVAL(outbuf,smb_vwv1,conn->cnum);
190 SSVAL(outbuf,smb_tid,conn->cnum);
192 DEBUG(3,("tcon service=%s cnum=%d\n",
193 service, conn->cnum));
195 END_PROFILE(SMBtcon);
199 /****************************************************************************
200 Reply to a tcon and X.
201 ****************************************************************************/
203 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
209 uint16 vuid = SVAL(inbuf,smb_uid);
210 int passlen = SVAL(inbuf,smb_vwv3);
213 extern BOOL global_encrypted_passwords_negotiated;
214 START_PROFILE(SMBtconX);
216 *service = *devicename = 0;
218 /* we might have to close an old one */
219 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
220 close_cnum(conn,vuid);
223 if (passlen > MAX_PASS_LEN) {
224 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
227 if (global_encrypted_passwords_negotiated) {
228 password = data_blob(smb_buf(inbuf),passlen);
230 password = data_blob(smb_buf(inbuf),passlen+1);
231 /* Ensure correct termination */
232 password.data[passlen]=0;
235 p = smb_buf(inbuf) + passlen;
236 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
239 * the service name can be either: \\server\share
240 * or share directly like on the DELL PowerVault 705
243 q = strchr_m(path+2,'\\');
245 END_PROFILE(SMBtconX);
246 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
248 fstrcpy(service,q+1);
251 fstrcpy(service,path);
253 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
255 DEBUG(4,("Got device type %s\n",devicename));
257 conn = make_connection(service,password,devicename,vuid,&nt_status);
259 data_blob_clear_free(&password);
262 END_PROFILE(SMBtconX);
263 return ERROR_NT(nt_status);
266 if (Protocol < PROTOCOL_NT1) {
267 set_message(outbuf,2,0,True);
269 p += srvstr_push(outbuf, p, devicename, -1,
270 STR_TERMINATE|STR_ASCII);
271 set_message_end(outbuf,p);
273 /* NT sets the fstype of IPC$ to the null string */
274 const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
275 const char *devicetype;
278 set_message(outbuf,3,0,True);
282 else if ( IS_PRINT(conn) )
288 p += srvstr_push(outbuf, p, IS_IPC(conn) ? "IPC" : devicetype, -1,
289 STR_TERMINATE|STR_ASCII);
290 p += srvstr_push(outbuf, p, fsname, -1,
293 set_message_end(outbuf,p);
295 /* what does setting this bit do? It is set by NT4 and
296 may affect the ability to autorun mounted cdroms */
297 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
298 (lp_csc_policy(SNUM(conn)) << 2));
300 init_dfsroot(conn, inbuf, outbuf);
304 DEBUG(3,("tconX service=%s \n",
307 /* set the incoming and outgoing tid to the just created one */
308 SSVAL(inbuf,smb_tid,conn->cnum);
309 SSVAL(outbuf,smb_tid,conn->cnum);
311 END_PROFILE(SMBtconX);
312 return chain_reply(inbuf,outbuf,length,bufsize);
315 /****************************************************************************
316 Reply to an unknown type.
317 ****************************************************************************/
319 int reply_unknown(char *inbuf,char *outbuf)
322 type = CVAL(inbuf,smb_com);
324 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
325 smb_fn_name(type), type, type));
327 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
330 /****************************************************************************
332 ****************************************************************************/
334 int reply_ioctl(connection_struct *conn,
335 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
337 uint16 device = SVAL(inbuf,smb_vwv1);
338 uint16 function = SVAL(inbuf,smb_vwv2);
339 uint32 ioctl_code = (device << 16) + function;
340 int replysize, outsize;
342 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
343 START_PROFILE(SMBioctl);
345 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
347 switch (ioctl_code) {
348 case IOCTL_QUERY_JOB_INFO:
352 END_PROFILE(SMBioctl);
353 return(ERROR_DOS(ERRSRV,ERRnosupport));
356 outsize = set_message(outbuf,8,replysize+1,True);
357 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
358 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
359 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
360 p = smb_buf(outbuf) + 1; /* Allow for alignment */
362 switch (ioctl_code) {
363 case IOCTL_QUERY_JOB_INFO:
365 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
366 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
367 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
372 END_PROFILE(SMBioctl);
376 /****************************************************************************
378 ****************************************************************************/
380 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
386 BOOL bad_path = False;
387 SMB_STRUCT_STAT sbuf;
388 START_PROFILE(SMBchkpth);
390 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
392 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
394 unix_convert(name,conn,0,&bad_path,&sbuf);
396 mode = SVAL(inbuf,smb_vwv0);
398 if (check_name(name,conn)) {
399 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
400 ok = S_ISDIR(sbuf.st_mode);
404 /* We special case this - as when a Windows machine
405 is parsing a path is steps through the components
406 one at a time - if a component fails it expects
407 ERRbadpath, not ERRbadfile.
410 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
412 return(UNIXERROR(ERRDOS,ERRbadpath));
415 outsize = set_message(outbuf,0,0,True);
417 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
419 END_PROFILE(SMBchkpth);
423 /****************************************************************************
425 ****************************************************************************/
427 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
431 SMB_STRUCT_STAT sbuf;
436 BOOL bad_path = False;
438 START_PROFILE(SMBgetatr);
440 p = smb_buf(inbuf) + 1;
441 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
443 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
445 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
446 under WfWg - weird! */
448 mode = aHIDDEN | aDIR;
449 if (!CAN_WRITE(conn))
455 unix_convert(fname,conn,0,&bad_path,&sbuf);
456 if (check_name(fname,conn)) {
457 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) {
458 mode = dos_mode(conn,fname,&sbuf);
460 mtime = sbuf.st_mtime;
465 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
471 set_bad_path_error(errno, bad_path);
472 END_PROFILE(SMBgetatr);
473 return(UNIXERROR(ERRDOS,ERRbadfile));
476 outsize = set_message(outbuf,10,0,True);
478 SSVAL(outbuf,smb_vwv0,mode);
479 if(lp_dos_filetime_resolution(SNUM(conn)) )
480 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
482 put_dos_date3(outbuf,smb_vwv1,mtime);
483 SIVAL(outbuf,smb_vwv3,(uint32)size);
485 if (Protocol >= PROTOCOL_NT1)
486 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
488 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
490 END_PROFILE(SMBgetatr);
494 /****************************************************************************
496 ****************************************************************************/
498 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
505 SMB_STRUCT_STAT sbuf;
506 BOOL bad_path = False;
509 START_PROFILE(SMBsetatr);
511 p = smb_buf(inbuf) + 1;
512 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
513 unix_convert(fname,conn,0,&bad_path,&sbuf);
515 mode = SVAL(inbuf,smb_vwv0);
516 mtime = make_unix_date3(inbuf+smb_vwv1);
518 if (VALID_STAT_OF_DIR(sbuf))
523 if (check_name(fname,conn))
524 ok = (file_chmod(conn,fname,mode,NULL) == 0);
526 ok = set_filetime(conn,fname,mtime);
529 set_bad_path_error(errno, bad_path);
530 END_PROFILE(SMBsetatr);
531 return(UNIXERROR(ERRDOS,ERRnoaccess));
534 outsize = set_message(outbuf,0,0,True);
536 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
538 END_PROFILE(SMBsetatr);
542 /****************************************************************************
544 ****************************************************************************/
546 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
549 SMB_BIG_UINT dfree,dsize,bsize;
550 START_PROFILE(SMBdskattr);
552 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
554 outsize = set_message(outbuf,5,0,True);
556 if (Protocol <= PROTOCOL_LANMAN2) {
557 double total_space, free_space;
558 /* we need to scale this to a number that DOS6 can handle. We
559 use floating point so we can handle large drives on systems
560 that don't have 64 bit integers
562 we end up displaying a maximum of 2G to DOS systems
564 total_space = dsize * (double)bsize;
565 free_space = dfree * (double)bsize;
567 dsize = (total_space+63*512) / (64*512);
568 dfree = (free_space+63*512) / (64*512);
570 if (dsize > 0xFFFF) dsize = 0xFFFF;
571 if (dfree > 0xFFFF) dfree = 0xFFFF;
573 SSVAL(outbuf,smb_vwv0,dsize);
574 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
575 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
576 SSVAL(outbuf,smb_vwv3,dfree);
578 SSVAL(outbuf,smb_vwv0,dsize);
579 SSVAL(outbuf,smb_vwv1,bsize/512);
580 SSVAL(outbuf,smb_vwv2,512);
581 SSVAL(outbuf,smb_vwv3,dfree);
584 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
586 END_PROFILE(SMBdskattr);
590 /****************************************************************************
592 Can be called from SMBsearch, SMBffirst or SMBfunique.
593 ****************************************************************************/
595 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
606 BOOL finished = False;
615 BOOL check_descend = False;
616 BOOL expect_close = False;
617 BOOL can_open = True;
618 BOOL bad_path = False;
619 START_PROFILE(SMBsearch);
621 *mask = *directory = *fname = 0;
623 /* If we were called as SMBffirst then we must expect close. */
624 if(CVAL(inbuf,smb_com) == SMBffirst)
627 outsize = set_message(outbuf,1,3,True);
628 maxentries = SVAL(inbuf,smb_vwv0);
629 dirtype = SVAL(inbuf,smb_vwv1);
630 p = smb_buf(inbuf) + 1;
631 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
633 status_len = SVAL(p, 0);
636 /* dirtype &= ~aDIR; */
638 if (status_len == 0) {
639 SMB_STRUCT_STAT sbuf;
642 pstrcpy(directory,path);
644 unix_convert(directory,conn,0,&bad_path,&sbuf);
647 if (!check_name(directory,conn))
650 p = strrchr_m(dir2,'/');
659 p = strrchr_m(directory,'/');
665 if (strlen(directory) == 0)
666 pstrcpy(directory,".");
667 memset((char *)status,'\0',21);
668 SCVAL(status,0,(dirtype & 0x1F));
673 status_dirtype = CVAL(status,0) & 0x1F;
674 if (status_dirtype != (dirtype & 0x1F))
675 dirtype = status_dirtype;
677 conn->dirptr = dptr_fetch(status+12,&dptr_num);
680 string_set(&conn->dirpath,dptr_path(dptr_num));
681 pstrcpy(mask, dptr_wcard(dptr_num));
685 p = smb_buf(outbuf) + 3;
688 if (status_len == 0) {
689 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
692 set_bad_path_error(errno, bad_path);
693 END_PROFILE(SMBsearch);
694 return (UNIXERROR(ERRDOS,ERRnofids));
696 END_PROFILE(SMBsearch);
697 return ERROR_DOS(ERRDOS,ERRnofids);
699 dptr_set_wcard(dptr_num, strdup(mask));
700 dptr_set_attr(dptr_num, dirtype);
702 dirtype = dptr_attr(dptr_num);
705 DEBUG(4,("dptr_num is %d\n",dptr_num));
708 if ((dirtype&0x1F) == aVOLID) {
710 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
711 dptr_fill(p+12,dptr_num);
712 if (dptr_zero(p+12) && (status_len==0))
716 p += DIR_STRUCT_SIZE;
718 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
719 conn->dirpath,lp_dontdescend(SNUM(conn))));
720 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
721 check_descend = True;
723 for (i=numentries;(i<maxentries) && !finished;i++) {
724 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
727 make_dir_struct(p,mask,fname,size,mode,date);
728 dptr_fill(p+12,dptr_num);
731 p += DIR_STRUCT_SIZE;
740 if (numentries == 0 || !ok) {
741 SCVAL(outbuf,smb_rcls,ERRDOS);
742 SSVAL(outbuf,smb_err,ERRnofiles);
743 dptr_close(&dptr_num);
746 /* If we were called as SMBffirst with smb_search_id == NULL
747 and no entries were found then return error and close dirptr
750 if(ok && expect_close && numentries == 0 && status_len == 0) {
751 SCVAL(outbuf,smb_rcls,ERRDOS);
752 SSVAL(outbuf,smb_err,ERRnofiles);
753 /* Also close the dptr - we know it's gone */
754 dptr_close(&dptr_num);
757 /* If we were called as SMBfunique, then we can close the dirptr now ! */
758 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
759 dptr_close(&dptr_num);
761 SSVAL(outbuf,smb_vwv0,numentries);
762 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
763 SCVAL(smb_buf(outbuf),0,5);
764 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
766 if (Protocol >= PROTOCOL_NT1)
767 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
769 outsize += DIR_STRUCT_SIZE*numentries;
770 smb_setlen(outbuf,outsize - 4);
772 if ((! *directory) && dptr_path(dptr_num))
773 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
775 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
776 smb_fn_name(CVAL(inbuf,smb_com)),
777 mask, directory, dirtype, numentries, maxentries ) );
779 END_PROFILE(SMBsearch);
783 /****************************************************************************
784 Reply to a fclose (stop directory search).
785 ****************************************************************************/
787 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
796 START_PROFILE(SMBfclose);
798 outsize = set_message(outbuf,1,0,True);
799 p = smb_buf(inbuf) + 1;
800 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
802 status_len = SVAL(p,0);
805 if (status_len == 0) {
806 END_PROFILE(SMBfclose);
807 return ERROR_DOS(ERRSRV,ERRsrverror);
812 if(dptr_fetch(status+12,&dptr_num)) {
813 /* Close the dptr - we know it's gone */
814 dptr_close(&dptr_num);
817 SSVAL(outbuf,smb_vwv0,0);
819 DEBUG(3,("search close\n"));
821 END_PROFILE(SMBfclose);
825 /****************************************************************************
827 ****************************************************************************/
829 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
839 SMB_STRUCT_STAT sbuf;
840 BOOL bad_path = False;
842 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
843 START_PROFILE(SMBopen);
845 share_mode = SVAL(inbuf,smb_vwv0);
847 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
849 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
851 unix_convert(fname,conn,0,&bad_path,&sbuf);
853 unixmode = unix_mode(conn,aARCH,fname);
855 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
856 unixmode, oplock_request,&rmode,NULL);
859 set_bad_path_error(errno, bad_path);
860 END_PROFILE(SMBopen);
861 return(UNIXERROR(ERRDOS,ERRnoaccess));
865 fmode = dos_mode(conn,fname,&sbuf);
866 mtime = sbuf.st_mtime;
869 DEBUG(3,("attempt to open a directory %s\n",fname));
870 close_file(fsp,False);
871 END_PROFILE(SMBopen);
872 return ERROR_DOS(ERRDOS,ERRnoaccess);
875 outsize = set_message(outbuf,7,0,True);
876 SSVAL(outbuf,smb_vwv0,fsp->fnum);
877 SSVAL(outbuf,smb_vwv1,fmode);
878 if(lp_dos_filetime_resolution(SNUM(conn)) )
879 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
881 put_dos_date3(outbuf,smb_vwv2,mtime);
882 SIVAL(outbuf,smb_vwv4,(uint32)size);
883 SSVAL(outbuf,smb_vwv6,rmode);
885 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
886 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
888 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
889 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
890 END_PROFILE(SMBopen);
894 /****************************************************************************
895 Reply to an open and X.
896 ****************************************************************************/
898 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
901 int smb_mode = SVAL(inbuf,smb_vwv3);
902 int smb_attr = SVAL(inbuf,smb_vwv5);
903 /* Breakout the oplock request bits so we can set the
904 reply bits separately. */
905 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
906 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
907 BOOL oplock_request = ex_oplock_request | core_oplock_request;
909 int open_flags = SVAL(inbuf,smb_vwv2);
910 int smb_sattr = SVAL(inbuf,smb_vwv4);
911 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
913 int smb_ofun = SVAL(inbuf,smb_vwv8);
916 int fmode=0,mtime=0,rmode=0;
917 SMB_STRUCT_STAT sbuf;
919 BOOL bad_path = False;
921 START_PROFILE(SMBopenX);
923 /* If it's an IPC, pass off the pipe handler. */
925 if (lp_nt_pipe_support()) {
926 END_PROFILE(SMBopenX);
927 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
929 END_PROFILE(SMBopenX);
930 return ERROR_DOS(ERRSRV,ERRaccess);
934 /* XXXX we need to handle passed times, sattr and flags */
935 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
937 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
939 unix_convert(fname,conn,0,&bad_path,&sbuf);
941 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
943 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
944 oplock_request, &rmode,&smb_action);
947 set_bad_path_error(errno, bad_path);
948 END_PROFILE(SMBopenX);
949 return(UNIXERROR(ERRDOS,ERRnoaccess));
953 fmode = dos_mode(conn,fname,&sbuf);
954 mtime = sbuf.st_mtime;
956 close_file(fsp,False);
957 END_PROFILE(SMBopenX);
958 return ERROR_DOS(ERRDOS,ERRnoaccess);
961 /* If the caller set the extended oplock request bit
962 and we granted one (by whatever means) - set the
963 correct bit for extended oplock reply.
966 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
967 smb_action |= EXTENDED_OPLOCK_GRANTED;
969 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
970 smb_action |= EXTENDED_OPLOCK_GRANTED;
972 /* If the caller set the core oplock request bit
973 and we granted one (by whatever means) - set the
974 correct bit for core oplock reply.
977 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
978 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
980 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
981 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
983 set_message(outbuf,15,0,True);
984 SSVAL(outbuf,smb_vwv2,fsp->fnum);
985 SSVAL(outbuf,smb_vwv3,fmode);
986 if(lp_dos_filetime_resolution(SNUM(conn)) )
987 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
989 put_dos_date3(outbuf,smb_vwv4,mtime);
990 SIVAL(outbuf,smb_vwv6,(uint32)size);
991 SSVAL(outbuf,smb_vwv8,rmode);
992 SSVAL(outbuf,smb_vwv11,smb_action);
994 END_PROFILE(SMBopenX);
995 return chain_reply(inbuf,outbuf,length,bufsize);
998 /****************************************************************************
999 Reply to a SMBulogoffX.
1000 ****************************************************************************/
1002 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1004 uint16 vuid = SVAL(inbuf,smb_uid);
1005 user_struct *vuser = get_valid_user_struct(vuid);
1006 START_PROFILE(SMBulogoffX);
1009 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1011 /* in user level security we are supposed to close any files
1012 open by this user */
1013 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1014 file_close_user(vuid);
1016 invalidate_vuid(vuid);
1018 set_message(outbuf,2,0,True);
1020 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1022 END_PROFILE(SMBulogoffX);
1023 return chain_reply(inbuf,outbuf,length,bufsize);
1026 /****************************************************************************
1027 Reply to a mknew or a create.
1028 ****************************************************************************/
1030 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1038 BOOL bad_path = False;
1040 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1041 SMB_STRUCT_STAT sbuf;
1042 START_PROFILE(SMBcreate);
1044 com = SVAL(inbuf,smb_com);
1046 createmode = SVAL(inbuf,smb_vwv0);
1047 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1049 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1051 unix_convert(fname,conn,0,&bad_path,&sbuf);
1053 if (createmode & aVOLID)
1054 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1056 unixmode = unix_mode(conn,createmode,fname);
1058 if(com == SMBmknew) {
1059 /* We should fail if file exists. */
1060 ofun = FILE_CREATE_IF_NOT_EXIST;
1062 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1063 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1066 /* Open file in dos compatibility share mode. */
1067 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1068 ofun, unixmode, oplock_request, NULL, NULL);
1071 set_bad_path_error(errno, bad_path);
1072 END_PROFILE(SMBcreate);
1073 return(UNIXERROR(ERRDOS,ERRnoaccess));
1076 outsize = set_message(outbuf,1,0,True);
1077 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1079 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1080 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1082 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1083 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1085 DEBUG( 2, ( "new file %s\n", fname ) );
1086 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1088 END_PROFILE(SMBcreate);
1092 /****************************************************************************
1093 Reply to a create temporary file.
1094 ****************************************************************************/
1096 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1102 BOOL bad_path = False;
1104 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1106 SMB_STRUCT_STAT sbuf;
1109 START_PROFILE(SMBctemp);
1111 createmode = SVAL(inbuf,smb_vwv0);
1112 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1113 pstrcat(fname,"\\TMXXXXXX");
1115 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1117 unix_convert(fname,conn,0,&bad_path,&sbuf);
1119 unixmode = unix_mode(conn,createmode,fname);
1121 tmpfd = smb_mkstemp(fname);
1123 END_PROFILE(SMBctemp);
1124 return(UNIXERROR(ERRDOS,ERRnoaccess));
1127 vfs_stat(conn,fname,&sbuf);
1129 /* Open file in dos compatibility share mode. */
1130 /* We should fail if file does not exist. */
1131 fsp = open_file_shared(conn,fname,&sbuf,
1132 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1133 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1134 unixmode, oplock_request, NULL, NULL);
1136 /* close fd from smb_mkstemp() */
1140 set_bad_path_error(errno, bad_path);
1141 END_PROFILE(SMBctemp);
1142 return(UNIXERROR(ERRDOS,ERRnoaccess));
1145 outsize = set_message(outbuf,1,0,True);
1146 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1148 /* the returned filename is relative to the directory */
1149 s = strrchr_m(fname, '/');
1155 p = smb_buf(outbuf);
1156 SSVALS(p, 0, -1); /* what is this? not in spec */
1157 SSVAL(p, 2, strlen(s));
1159 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1160 outsize = set_message_end(outbuf, p);
1162 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1163 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1165 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1166 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1168 DEBUG( 2, ( "created temp file %s\n", fname ) );
1169 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1170 fname, fsp->fd, createmode, (int)unixmode ) );
1172 END_PROFILE(SMBctemp);
1176 /*******************************************************************
1177 Check if a user is allowed to rename a file.
1178 ********************************************************************/
1180 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1186 if (!CAN_WRITE(conn))
1187 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1189 if (S_ISDIR(pst->st_mode))
1190 return NT_STATUS_OK;
1192 /* We need a better way to return NT status codes from open... */
1196 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1197 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1200 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1201 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1202 ret = NT_STATUS_SHARING_VIOLATION;
1207 close_file(fsp,False);
1208 return NT_STATUS_OK;
1211 /*******************************************************************
1212 Check if a user is allowed to delete a file.
1213 ********************************************************************/
1215 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1217 SMB_STRUCT_STAT sbuf;
1223 if (!CAN_WRITE(conn))
1224 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1226 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1227 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1229 fmode = dos_mode(conn,fname,&sbuf);
1231 return NT_STATUS_FILE_IS_A_DIRECTORY;
1232 if (!lp_delete_readonly(SNUM(conn))) {
1234 return NT_STATUS_CANNOT_DELETE;
1236 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1237 return NT_STATUS_CANNOT_DELETE;
1239 /* We need a better way to return NT status codes from open... */
1243 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1244 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1247 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1248 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1249 ret = unix_ERR_ntstatus;
1250 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1251 ret = NT_STATUS_SHARING_VIOLATION;
1254 unix_ERR_ntstatus = NT_STATUS_OK;
1257 close_file(fsp,False);
1258 return NT_STATUS_OK;
1261 /****************************************************************************
1262 The guts of the unlink command, split out so it may be called by the NT SMB
1264 ****************************************************************************/
1266 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1272 NTSTATUS error = NT_STATUS_OK;
1274 BOOL bad_path = False;
1276 SMB_STRUCT_STAT sbuf;
1278 *directory = *mask = 0;
1280 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1282 p = strrchr_m(name,'/');
1284 pstrcpy(directory,".");
1288 pstrcpy(directory,name);
1293 * We should only check the mangled cache
1294 * here if unix_convert failed. This means
1295 * that the path in 'mask' doesn't exist
1296 * on the file system and so we need to look
1297 * for a possible mangle. This patch from
1298 * Tine Smukavec <valentin.smukavec@hermes.si>.
1301 if (!rc && mangle_is_mangled(mask))
1302 mangle_check_cache( mask );
1304 has_wild = ms_has_wild(mask);
1307 pstrcat(directory,"/");
1308 pstrcat(directory,mask);
1309 error = can_delete(directory,conn,dirtype);
1310 if (!NT_STATUS_IS_OK(error)) return error;
1312 if (vfs_unlink(conn,directory) == 0) {
1316 void *dirptr = NULL;
1319 if (check_name(directory,conn))
1320 dirptr = OpenDir(conn, directory, True);
1322 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1323 the pattern matches against the long name, otherwise the short name
1324 We don't implement this yet XXXX
1328 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1330 if (strequal(mask,"????????.???"))
1333 while ((dname = ReadDirName(dirptr))) {
1335 pstrcpy(fname,dname);
1337 if(!mask_match(fname, mask, case_sensitive)) continue;
1339 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1340 error = can_delete(fname,conn,dirtype);
1341 if (!NT_STATUS_IS_OK(error)) continue;
1342 if (vfs_unlink(conn,fname) == 0) count++;
1343 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1349 if (count == 0 && NT_STATUS_IS_OK(error)) {
1350 error = map_nt_error_from_unix(errno);
1356 /****************************************************************************
1358 ****************************************************************************/
1360 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1367 START_PROFILE(SMBunlink);
1369 dirtype = SVAL(inbuf,smb_vwv0);
1371 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1373 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1375 DEBUG(3,("reply_unlink : %s\n",name));
1377 status = unlink_internals(conn, dirtype, name);
1378 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1381 * Win2k needs a changenotify request response before it will
1382 * update after a rename..
1384 process_pending_change_notify_queue((time_t)0);
1386 outsize = set_message(outbuf,0,0,True);
1388 END_PROFILE(SMBunlink);
1392 /****************************************************************************
1394 ****************************************************************************/
1396 void fail_readraw(void)
1399 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1401 exit_server(errstr);
1404 /****************************************************************************
1405 Use sendfile in readbraw.
1406 ****************************************************************************/
1408 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1409 ssize_t mincount, char *outbuf)
1413 #if defined(WITH_SENDFILE)
1415 * We can only use sendfile on a non-chained packet and on a file
1416 * that is exclusively oplocked. reply_readbraw has already checked the length.
1419 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1420 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1423 _smb_setlen(outbuf,nread);
1424 header.data = outbuf;
1428 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1430 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1431 * return ENOSYS then pretend we just got a normal read.
1433 if (errno == ENOSYS)
1436 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1437 fsp->fsp_name, strerror(errno) ));
1438 exit_server("send_file_readbraw sendfile failed");
1447 ret = read_file(fsp,outbuf+4,startpos,nread);
1452 _smb_setlen(outbuf,ret);
1453 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1457 /****************************************************************************
1458 Reply to a readbraw (core+ protocol).
1459 ****************************************************************************/
1461 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1463 ssize_t maxcount,mincount;
1466 char *header = outbuf;
1468 START_PROFILE(SMBreadbraw);
1471 * Special check if an oplock break has been issued
1472 * and the readraw request croses on the wire, we must
1473 * return a zero length response here.
1476 if(global_oplock_break) {
1477 _smb_setlen(header,0);
1478 if (write_data(smbd_server_fd(),header,4) != 4)
1480 DEBUG(5,("readbraw - oplock break finished\n"));
1481 END_PROFILE(SMBreadbraw);
1485 fsp = file_fsp(inbuf,smb_vwv0);
1487 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1489 * fsp could be NULL here so use the value from the packet. JRA.
1491 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1492 _smb_setlen(header,0);
1493 if (write_data(smbd_server_fd(),header,4) != 4)
1495 END_PROFILE(SMBreadbraw);
1499 CHECK_FSP(fsp,conn);
1501 flush_write_cache(fsp, READRAW_FLUSH);
1503 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1504 if(CVAL(inbuf,smb_wct) == 10) {
1506 * This is a large offset (64 bit) read.
1508 #ifdef LARGE_SMB_OFF_T
1510 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1512 #else /* !LARGE_SMB_OFF_T */
1515 * Ensure we haven't been sent a >32 bit offset.
1518 if(IVAL(inbuf,smb_vwv8) != 0) {
1519 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1520 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1521 _smb_setlen(header,0);
1522 if (write_data(smbd_server_fd(),header,4) != 4)
1524 END_PROFILE(SMBreadbraw);
1528 #endif /* LARGE_SMB_OFF_T */
1531 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1532 _smb_setlen(header,0);
1533 if (write_data(smbd_server_fd(),header,4) != 4)
1535 END_PROFILE(SMBreadbraw);
1539 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1540 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1542 /* ensure we don't overrun the packet size */
1543 maxcount = MIN(65535,maxcount);
1544 maxcount = MAX(mincount,maxcount);
1546 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1547 SMB_OFF_T size = fsp->size;
1548 SMB_OFF_T sizeneeded = startpos + maxcount;
1550 if (size < sizeneeded) {
1552 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1554 if (!fsp->can_write)
1558 if (startpos >= size)
1561 nread = MIN(maxcount,(size - startpos));
1564 if (nread < mincount)
1567 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1568 (int)maxcount, (int)mincount, (int)nread ) );
1570 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1572 DEBUG(5,("readbraw finished\n"));
1573 END_PROFILE(SMBreadbraw);
1577 /****************************************************************************
1578 Reply to a lockread (core+ protocol).
1579 ****************************************************************************/
1581 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1589 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1590 START_PROFILE(SMBlockread);
1592 CHECK_FSP(fsp,conn);
1595 release_level_2_oplocks_on_change(fsp);
1597 numtoread = SVAL(inbuf,smb_vwv1);
1598 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1600 outsize = set_message(outbuf,5,3,True);
1601 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1602 data = smb_buf(outbuf) + 3;
1605 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1606 * protocol request that predates the read/write lock concept.
1607 * Thus instead of asking for a read lock here we need to ask
1608 * for a write lock. JRA.
1611 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1612 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1614 if (NT_STATUS_V(status)) {
1615 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1617 * A blocking lock was requested. Package up
1618 * this smb into a queued request and push it
1619 * onto the blocking lock queue.
1621 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1622 (SMB_BIG_UINT)numtoread)) {
1623 END_PROFILE(SMBlockread);
1627 END_PROFILE(SMBlockread);
1628 return ERROR_NT(status);
1631 nread = read_file(fsp,data,startpos,numtoread);
1634 END_PROFILE(SMBlockread);
1635 return(UNIXERROR(ERRDOS,ERRnoaccess));
1639 SSVAL(outbuf,smb_vwv0,nread);
1640 SSVAL(outbuf,smb_vwv5,nread+3);
1641 SSVAL(smb_buf(outbuf),1,nread);
1643 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1644 fsp->fnum, (int)numtoread, (int)nread));
1646 END_PROFILE(SMBlockread);
1650 /****************************************************************************
1652 ****************************************************************************/
1654 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1661 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1662 START_PROFILE(SMBread);
1664 CHECK_FSP(fsp,conn);
1667 numtoread = SVAL(inbuf,smb_vwv1);
1668 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1670 outsize = set_message(outbuf,5,3,True);
1671 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1672 data = smb_buf(outbuf) + 3;
1674 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1675 END_PROFILE(SMBread);
1676 return ERROR_DOS(ERRDOS,ERRlock);
1680 nread = read_file(fsp,data,startpos,numtoread);
1683 END_PROFILE(SMBread);
1684 return(UNIXERROR(ERRDOS,ERRnoaccess));
1688 SSVAL(outbuf,smb_vwv0,nread);
1689 SSVAL(outbuf,smb_vwv5,nread+3);
1690 SCVAL(smb_buf(outbuf),0,1);
1691 SSVAL(smb_buf(outbuf),1,nread);
1693 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1694 fsp->fnum, (int)numtoread, (int)nread ) );
1696 END_PROFILE(SMBread);
1700 /****************************************************************************
1701 Reply to a read and X - possibly using sendfile.
1702 ****************************************************************************/
1704 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1705 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1708 char *data = smb_buf(outbuf);
1710 #if defined(WITH_SENDFILE)
1712 * We can only use sendfile on a non-chained packet and on a file
1713 * that is exclusively oplocked.
1716 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1717 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1718 SMB_STRUCT_STAT sbuf;
1721 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
1722 return(UNIXERROR(ERRDOS,ERRnoaccess));
1724 if (startpos > sbuf.st_size)
1727 if (smb_maxcnt > (sbuf.st_size - startpos))
1728 smb_maxcnt = (sbuf.st_size - startpos);
1730 if (smb_maxcnt == 0)
1734 * Set up the packet header before send. We
1735 * assume here the sendfile will work (get the
1736 * correct amount of data).
1739 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1740 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1741 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1742 SCVAL(outbuf,smb_vwv0,0xFF);
1743 set_message(outbuf,12,smb_maxcnt,False);
1744 header.data = outbuf;
1745 header.length = data - outbuf;
1748 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1750 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1751 * return ENOSYS then pretend we just got a normal read.
1753 if (errno == ENOSYS)
1756 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1757 fsp->fsp_name, strerror(errno) ));
1758 exit_server("send_file_readX sendfile failed");
1761 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1762 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1770 nread = read_file(fsp,data,startpos,smb_maxcnt);
1773 END_PROFILE(SMBreadX);
1774 return(UNIXERROR(ERRDOS,ERRnoaccess));
1777 SSVAL(outbuf,smb_vwv5,nread);
1778 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1779 SSVAL(smb_buf(outbuf),-2,nread);
1781 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1782 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1787 /****************************************************************************
1788 Reply to a read and X.
1789 ****************************************************************************/
1791 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1793 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1794 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1796 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1798 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1801 START_PROFILE(SMBreadX);
1803 /* If it's an IPC, pass off the pipe handler. */
1805 END_PROFILE(SMBreadX);
1806 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1809 CHECK_FSP(fsp,conn);
1812 set_message(outbuf,12,0,True);
1814 if(CVAL(inbuf,smb_wct) == 12) {
1815 #ifdef LARGE_SMB_OFF_T
1817 * This is a large offset (64 bit) read.
1819 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1821 #else /* !LARGE_SMB_OFF_T */
1824 * Ensure we haven't been sent a >32 bit offset.
1827 if(IVAL(inbuf,smb_vwv10) != 0) {
1828 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1829 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1830 END_PROFILE(SMBreadX);
1831 return ERROR_DOS(ERRDOS,ERRbadaccess);
1834 #endif /* LARGE_SMB_OFF_T */
1838 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1839 END_PROFILE(SMBreadX);
1840 return ERROR_DOS(ERRDOS,ERRlock);
1843 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1845 nread = chain_reply(inbuf,outbuf,length,bufsize);
1847 END_PROFILE(SMBreadX);
1851 /****************************************************************************
1852 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1853 ****************************************************************************/
1855 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1858 ssize_t total_written=0;
1859 size_t numtowrite=0;
1864 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1866 START_PROFILE(SMBwritebraw);
1868 CHECK_FSP(fsp,conn);
1871 tcount = IVAL(inbuf,smb_vwv1);
1872 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1873 write_through = BITSETW(inbuf+smb_vwv7,0);
1875 /* We have to deal with slightly different formats depending
1876 on whether we are using the core+ or lanman1.0 protocol */
1878 if(Protocol <= PROTOCOL_COREPLUS) {
1879 numtowrite = SVAL(smb_buf(inbuf),-2);
1880 data = smb_buf(inbuf);
1882 numtowrite = SVAL(inbuf,smb_vwv10);
1883 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1886 /* force the error type */
1887 SCVAL(inbuf,smb_com,SMBwritec);
1888 SCVAL(outbuf,smb_com,SMBwritec);
1890 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1891 END_PROFILE(SMBwritebraw);
1892 return(ERROR_DOS(ERRDOS,ERRlock));
1896 nwritten = write_file(fsp,data,startpos,numtowrite);
1898 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1899 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1901 if (nwritten < (ssize_t)numtowrite) {
1902 END_PROFILE(SMBwritebraw);
1903 return(UNIXERROR(ERRHRD,ERRdiskfull));
1906 total_written = nwritten;
1908 /* Return a message to the redirector to tell it to send more bytes */
1909 SCVAL(outbuf,smb_com,SMBwritebraw);
1910 SSVALS(outbuf,smb_vwv0,-1);
1911 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1912 if (!send_smb(smbd_server_fd(),outbuf))
1913 exit_server("reply_writebraw: send_smb failed.");
1915 /* Now read the raw data into the buffer and write it */
1916 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1917 exit_server("secondary writebraw failed");
1920 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1921 numtowrite = smb_len(inbuf);
1923 /* Set up outbuf to return the correct return */
1924 outsize = set_message(outbuf,1,0,True);
1925 SCVAL(outbuf,smb_com,SMBwritec);
1926 SSVAL(outbuf,smb_vwv0,total_written);
1928 if (numtowrite != 0) {
1930 if (numtowrite > BUFFER_SIZE) {
1931 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1932 (unsigned int)numtowrite ));
1933 exit_server("secondary writebraw failed");
1936 if (tcount > nwritten+numtowrite) {
1937 DEBUG(3,("Client overestimated the write %d %d %d\n",
1938 (int)tcount,(int)nwritten,(int)numtowrite));
1941 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1942 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1944 exit_server("secondary writebraw failed");
1947 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1949 if (nwritten < (ssize_t)numtowrite) {
1950 SCVAL(outbuf,smb_rcls,ERRHRD);
1951 SSVAL(outbuf,smb_err,ERRdiskfull);
1955 total_written += nwritten;
1958 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1959 sync_file(conn,fsp);
1961 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1962 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1964 /* we won't return a status if write through is not selected - this follows what WfWg does */
1965 END_PROFILE(SMBwritebraw);
1966 if (!write_through && total_written==tcount) {
1968 #if RABBIT_PELLET_FIX
1970 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1971 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1973 if (!send_keepalive(smbd_server_fd()))
1974 exit_server("reply_writebraw: send of keepalive failed");
1982 /****************************************************************************
1983 Reply to a writeunlock (core+).
1984 ****************************************************************************/
1986 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1987 int size, int dum_buffsize)
1989 ssize_t nwritten = -1;
1994 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1996 START_PROFILE(SMBwriteunlock);
1998 CHECK_FSP(fsp,conn);
2001 numtowrite = SVAL(inbuf,smb_vwv1);
2002 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2003 data = smb_buf(inbuf) + 3;
2005 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2006 WRITE_LOCK,False)) {
2007 END_PROFILE(SMBwriteunlock);
2008 return ERROR_DOS(ERRDOS,ERRlock);
2011 /* The special X/Open SMB protocol handling of
2012 zero length writes is *NOT* done for
2017 nwritten = write_file(fsp,data,startpos,numtowrite);
2019 if (lp_syncalways(SNUM(conn)))
2020 sync_file(conn,fsp);
2022 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2023 END_PROFILE(SMBwriteunlock);
2024 return(UNIXERROR(ERRHRD,ERRdiskfull));
2027 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2028 (SMB_BIG_UINT)startpos);
2029 if (NT_STATUS_V(status)) {
2030 END_PROFILE(SMBwriteunlock);
2031 return ERROR_NT(status);
2034 outsize = set_message(outbuf,1,0,True);
2036 SSVAL(outbuf,smb_vwv0,nwritten);
2038 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2039 fsp->fnum, (int)numtowrite, (int)nwritten));
2041 END_PROFILE(SMBwriteunlock);
2045 /****************************************************************************
2047 ****************************************************************************/
2049 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2052 ssize_t nwritten = -1;
2055 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2057 START_PROFILE(SMBwrite);
2059 /* If it's an IPC, pass off the pipe handler. */
2061 END_PROFILE(SMBwrite);
2062 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2065 CHECK_FSP(fsp,conn);
2068 numtowrite = SVAL(inbuf,smb_vwv1);
2069 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2070 data = smb_buf(inbuf) + 3;
2072 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2073 END_PROFILE(SMBwrite);
2074 return ERROR_DOS(ERRDOS,ERRlock);
2078 * X/Open SMB protocol says that if smb_vwv1 is
2079 * zero then the file size should be extended or
2080 * truncated to the size given in smb_vwv[2-3].
2083 if(numtowrite == 0) {
2085 * This is actually an allocate call, and set EOF. JRA.
2087 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2089 END_PROFILE(SMBwrite);
2090 return ERROR_NT(NT_STATUS_DISK_FULL);
2092 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2094 END_PROFILE(SMBwrite);
2095 return ERROR_NT(NT_STATUS_DISK_FULL);
2098 nwritten = write_file(fsp,data,startpos,numtowrite);
2100 if (lp_syncalways(SNUM(conn)))
2101 sync_file(conn,fsp);
2103 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2104 END_PROFILE(SMBwrite);
2105 return(UNIXERROR(ERRHRD,ERRdiskfull));
2108 outsize = set_message(outbuf,1,0,True);
2110 SSVAL(outbuf,smb_vwv0,nwritten);
2112 if (nwritten < (ssize_t)numtowrite) {
2113 SCVAL(outbuf,smb_rcls,ERRHRD);
2114 SSVAL(outbuf,smb_err,ERRdiskfull);
2117 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2119 END_PROFILE(SMBwrite);
2123 /****************************************************************************
2124 Reply to a write and X.
2125 ****************************************************************************/
2127 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2129 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2130 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2131 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2132 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2133 ssize_t nwritten = -1;
2134 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2135 unsigned int smblen = smb_len(inbuf);
2137 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2138 START_PROFILE(SMBwriteX);
2140 /* If it's an IPC, pass off the pipe handler. */
2142 END_PROFILE(SMBwriteX);
2143 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2146 CHECK_FSP(fsp,conn);
2149 /* Deal with possible LARGE_WRITEX */
2151 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2153 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2154 END_PROFILE(SMBwriteX);
2155 return ERROR_DOS(ERRDOS,ERRbadmem);
2158 data = smb_base(inbuf) + smb_doff;
2160 if(CVAL(inbuf,smb_wct) == 14) {
2161 #ifdef LARGE_SMB_OFF_T
2163 * This is a large offset (64 bit) write.
2165 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2167 #else /* !LARGE_SMB_OFF_T */
2170 * Ensure we haven't been sent a >32 bit offset.
2173 if(IVAL(inbuf,smb_vwv12) != 0) {
2174 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2175 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2176 END_PROFILE(SMBwriteX);
2177 return ERROR_DOS(ERRDOS,ERRbadaccess);
2180 #endif /* LARGE_SMB_OFF_T */
2183 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2184 END_PROFILE(SMBwriteX);
2185 return ERROR_DOS(ERRDOS,ERRlock);
2188 /* X/Open SMB protocol says that, unlike SMBwrite
2189 if the length is zero then NO truncation is
2190 done, just a write of zero. To truncate a file,
2196 nwritten = write_file(fsp,data,startpos,numtowrite);
2198 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2199 END_PROFILE(SMBwriteX);
2200 return(UNIXERROR(ERRHRD,ERRdiskfull));
2203 set_message(outbuf,6,0,True);
2205 SSVAL(outbuf,smb_vwv2,nwritten);
2207 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2209 if (nwritten < (ssize_t)numtowrite) {
2210 SCVAL(outbuf,smb_rcls,ERRHRD);
2211 SSVAL(outbuf,smb_err,ERRdiskfull);
2214 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2215 fsp->fnum, (int)numtowrite, (int)nwritten));
2217 if (lp_syncalways(SNUM(conn)) || write_through)
2218 sync_file(conn,fsp);
2220 END_PROFILE(SMBwriteX);
2221 return chain_reply(inbuf,outbuf,length,bufsize);
2224 /****************************************************************************
2226 ****************************************************************************/
2228 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2234 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2235 START_PROFILE(SMBlseek);
2237 CHECK_FSP(fsp,conn);
2239 flush_write_cache(fsp, SEEK_FLUSH);
2241 mode = SVAL(inbuf,smb_vwv1) & 3;
2242 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2243 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2260 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2262 * Check for the special case where a seek before the start
2263 * of the file sets the offset to zero. Added in the CIFS spec,
2267 if(errno == EINVAL) {
2268 SMB_OFF_T current_pos = startpos;
2270 if(umode == SEEK_CUR) {
2272 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2273 END_PROFILE(SMBlseek);
2274 return(UNIXERROR(ERRDOS,ERRnoaccess));
2277 current_pos += startpos;
2279 } else if (umode == SEEK_END) {
2281 SMB_STRUCT_STAT sbuf;
2283 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2284 END_PROFILE(SMBlseek);
2285 return(UNIXERROR(ERRDOS,ERRnoaccess));
2288 current_pos += sbuf.st_size;
2292 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2296 END_PROFILE(SMBlseek);
2297 return(UNIXERROR(ERRDOS,ERRnoaccess));
2303 outsize = set_message(outbuf,2,0,True);
2304 SIVAL(outbuf,smb_vwv0,res);
2306 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2307 fsp->fnum, (double)startpos, (double)res, mode));
2309 END_PROFILE(SMBlseek);
2313 /****************************************************************************
2315 ****************************************************************************/
2317 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2319 int outsize = set_message(outbuf,0,0,True);
2320 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2321 START_PROFILE(SMBflush);
2323 CHECK_FSP(fsp,conn);
2326 file_sync_all(conn);
2328 sync_file(conn,fsp);
2331 DEBUG(3,("flush\n"));
2332 END_PROFILE(SMBflush);
2336 /****************************************************************************
2338 ****************************************************************************/
2340 int reply_exit(connection_struct *conn,
2341 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2344 START_PROFILE(SMBexit);
2345 outsize = set_message(outbuf,0,0,True);
2347 DEBUG(3,("exit\n"));
2349 END_PROFILE(SMBexit);
2353 /****************************************************************************
2354 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2355 ****************************************************************************/
2357 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2362 int32 eclass = 0, err = 0;
2363 files_struct *fsp = NULL;
2364 START_PROFILE(SMBclose);
2366 outsize = set_message(outbuf,0,0,True);
2368 /* If it's an IPC, pass off to the pipe handler. */
2370 END_PROFILE(SMBclose);
2371 return reply_pipe_close(conn, inbuf,outbuf);
2374 fsp = file_fsp(inbuf,smb_vwv0);
2377 * We can only use CHECK_FSP if we know it's not a directory.
2380 if(!fsp || (fsp->conn != conn)) {
2381 END_PROFILE(SMBclose);
2382 return ERROR_DOS(ERRDOS,ERRbadfid);
2385 if(fsp->is_directory) {
2387 * Special case - close NT SMB directory handle.
2389 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2390 close_file(fsp,True);
2393 * Close ordinary file.
2398 /* Save the name for time set in close. */
2399 pstrcpy( file_name, fsp->fsp_name);
2401 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2403 conn->num_files_open));
2406 * close_file() returns the unix errno if an error
2407 * was detected on close - normally this is due to
2408 * a disk full error. If not then it was probably an I/O error.
2411 if((close_err = close_file(fsp,True)) != 0) {
2413 END_PROFILE(SMBclose);
2414 return (UNIXERROR(ERRHRD,ERRgeneral));
2418 * Now take care of any time sent in the close.
2421 mtime = make_unix_date3(inbuf+smb_vwv1);
2423 /* try and set the date */
2424 set_filetime(conn, file_name, mtime);
2428 /* We have a cached error */
2430 END_PROFILE(SMBclose);
2431 return ERROR_DOS(eclass,err);
2434 END_PROFILE(SMBclose);
2438 /****************************************************************************
2439 Reply to a writeclose (Core+ protocol).
2440 ****************************************************************************/
2442 int reply_writeclose(connection_struct *conn,
2443 char *inbuf,char *outbuf, int size, int dum_buffsize)
2446 ssize_t nwritten = -1;
2452 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2453 START_PROFILE(SMBwriteclose);
2455 CHECK_FSP(fsp,conn);
2458 numtowrite = SVAL(inbuf,smb_vwv1);
2459 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2460 mtime = make_unix_date3(inbuf+smb_vwv4);
2461 data = smb_buf(inbuf) + 1;
2463 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2464 END_PROFILE(SMBwriteclose);
2465 return ERROR_DOS(ERRDOS,ERRlock);
2468 nwritten = write_file(fsp,data,startpos,numtowrite);
2470 set_filetime(conn, fsp->fsp_name,mtime);
2472 close_err = close_file(fsp,True);
2474 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2475 fsp->fnum, (int)numtowrite, (int)nwritten,
2476 conn->num_files_open));
2478 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2479 END_PROFILE(SMBwriteclose);
2480 return(UNIXERROR(ERRHRD,ERRdiskfull));
2483 if(close_err != 0) {
2485 END_PROFILE(SMBwriteclose);
2486 return(UNIXERROR(ERRHRD,ERRgeneral));
2489 outsize = set_message(outbuf,1,0,True);
2491 SSVAL(outbuf,smb_vwv0,nwritten);
2492 END_PROFILE(SMBwriteclose);
2496 /****************************************************************************
2498 ****************************************************************************/
2500 int reply_lock(connection_struct *conn,
2501 char *inbuf,char *outbuf, int length, int dum_buffsize)
2503 int outsize = set_message(outbuf,0,0,True);
2504 SMB_BIG_UINT count,offset;
2506 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2507 START_PROFILE(SMBlock);
2509 CHECK_FSP(fsp,conn);
2511 release_level_2_oplocks_on_change(fsp);
2513 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2514 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2516 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2517 fsp->fd, fsp->fnum, (double)offset, (double)count));
2519 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2520 if (NT_STATUS_V(status)) {
2521 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2523 * A blocking lock was requested. Package up
2524 * this smb into a queued request and push it
2525 * onto the blocking lock queue.
2527 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2528 END_PROFILE(SMBlock);
2532 END_PROFILE(SMBlock);
2533 return ERROR_NT(status);
2536 END_PROFILE(SMBlock);
2540 /****************************************************************************
2542 ****************************************************************************/
2544 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2547 int outsize = set_message(outbuf,0,0,True);
2548 SMB_BIG_UINT count,offset;
2550 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2551 START_PROFILE(SMBunlock);
2553 CHECK_FSP(fsp,conn);
2555 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2556 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2558 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2559 if (NT_STATUS_V(status)) {
2560 END_PROFILE(SMBunlock);
2561 return ERROR_NT(status);
2564 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2565 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2567 END_PROFILE(SMBunlock);
2571 /****************************************************************************
2573 ****************************************************************************/
2575 int reply_tdis(connection_struct *conn,
2576 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2578 int outsize = set_message(outbuf,0,0,True);
2580 START_PROFILE(SMBtdis);
2582 vuid = SVAL(inbuf,smb_uid);
2585 DEBUG(4,("Invalid connection in tdis\n"));
2586 END_PROFILE(SMBtdis);
2587 return ERROR_DOS(ERRSRV,ERRinvnid);
2592 close_cnum(conn,vuid);
2594 END_PROFILE(SMBtdis);
2598 /****************************************************************************
2600 ****************************************************************************/
2602 int reply_echo(connection_struct *conn,
2603 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2605 int smb_reverb = SVAL(inbuf,smb_vwv0);
2607 unsigned int data_len = smb_buflen(inbuf);
2608 int outsize = set_message(outbuf,1,data_len,True);
2609 START_PROFILE(SMBecho);
2611 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2613 /* copy any incoming data back out */
2615 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2617 if (smb_reverb > 100) {
2618 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2622 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2623 SSVAL(outbuf,smb_vwv0,seq_num);
2625 smb_setlen(outbuf,outsize - 4);
2627 if (!send_smb(smbd_server_fd(),outbuf))
2628 exit_server("reply_echo: send_smb failed.");
2631 DEBUG(3,("echo %d times\n", smb_reverb));
2635 END_PROFILE(SMBecho);
2639 /****************************************************************************
2640 Reply to a printopen.
2641 ****************************************************************************/
2643 int reply_printopen(connection_struct *conn,
2644 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2648 START_PROFILE(SMBsplopen);
2650 if (!CAN_PRINT(conn)) {
2651 END_PROFILE(SMBsplopen);
2652 return ERROR_DOS(ERRDOS,ERRnoaccess);
2655 /* Open for exclusive use, write only. */
2656 fsp = print_fsp_open(conn, NULL);
2659 END_PROFILE(SMBsplopen);
2660 return(UNIXERROR(ERRDOS,ERRnoaccess));
2663 outsize = set_message(outbuf,1,0,True);
2664 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2666 DEBUG(3,("openprint fd=%d fnum=%d\n",
2667 fsp->fd, fsp->fnum));
2669 END_PROFILE(SMBsplopen);
2673 /****************************************************************************
2674 Reply to a printclose.
2675 ****************************************************************************/
2677 int reply_printclose(connection_struct *conn,
2678 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2680 int outsize = set_message(outbuf,0,0,True);
2681 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2683 START_PROFILE(SMBsplclose);
2685 CHECK_FSP(fsp,conn);
2687 if (!CAN_PRINT(conn)) {
2688 END_PROFILE(SMBsplclose);
2689 return ERROR_DOS(ERRDOS,ERRnoaccess);
2692 DEBUG(3,("printclose fd=%d fnum=%d\n",
2693 fsp->fd,fsp->fnum));
2695 close_err = close_file(fsp,True);
2697 if(close_err != 0) {
2699 END_PROFILE(SMBsplclose);
2700 return(UNIXERROR(ERRHRD,ERRgeneral));
2703 END_PROFILE(SMBsplclose);
2707 /****************************************************************************
2708 Reply to a printqueue.
2709 ****************************************************************************/
2711 int reply_printqueue(connection_struct *conn,
2712 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2714 int outsize = set_message(outbuf,2,3,True);
2715 int max_count = SVAL(inbuf,smb_vwv0);
2716 int start_index = SVAL(inbuf,smb_vwv1);
2717 START_PROFILE(SMBsplretq);
2719 /* we used to allow the client to get the cnum wrong, but that
2720 is really quite gross and only worked when there was only
2721 one printer - I think we should now only accept it if they
2722 get it right (tridge) */
2723 if (!CAN_PRINT(conn)) {
2724 END_PROFILE(SMBsplretq);
2725 return ERROR_DOS(ERRDOS,ERRnoaccess);
2728 SSVAL(outbuf,smb_vwv0,0);
2729 SSVAL(outbuf,smb_vwv1,0);
2730 SCVAL(smb_buf(outbuf),0,1);
2731 SSVAL(smb_buf(outbuf),1,0);
2733 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2734 start_index, max_count));
2737 print_queue_struct *queue = NULL;
2738 print_status_struct status;
2739 char *p = smb_buf(outbuf) + 3;
2740 int count = print_queue_status(SNUM(conn), &queue, &status);
2741 int num_to_get = ABS(max_count);
2742 int first = (max_count>0?start_index:start_index+max_count+1);
2748 num_to_get = MIN(num_to_get,count-first);
2751 for (i=first;i<first+num_to_get;i++) {
2752 put_dos_date2(p,0,queue[i].time);
2753 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2754 SSVAL(p,5, queue[i].job);
2755 SIVAL(p,7,queue[i].size);
2757 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2762 outsize = set_message(outbuf,2,28*count+3,False);
2763 SSVAL(outbuf,smb_vwv0,count);
2764 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2765 SCVAL(smb_buf(outbuf),0,1);
2766 SSVAL(smb_buf(outbuf),1,28*count);
2771 DEBUG(3,("%d entries returned in queue\n",count));
2774 END_PROFILE(SMBsplretq);
2778 /****************************************************************************
2779 Reply to a printwrite.
2780 ****************************************************************************/
2782 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2785 int outsize = set_message(outbuf,0,0,True);
2787 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2789 START_PROFILE(SMBsplwr);
2791 if (!CAN_PRINT(conn)) {
2792 END_PROFILE(SMBsplwr);
2793 return ERROR_DOS(ERRDOS,ERRnoaccess);
2796 CHECK_FSP(fsp,conn);
2799 numtowrite = SVAL(smb_buf(inbuf),1);
2800 data = smb_buf(inbuf) + 3;
2802 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2803 END_PROFILE(SMBsplwr);
2804 return(UNIXERROR(ERRHRD,ERRdiskfull));
2807 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2809 END_PROFILE(SMBsplwr);
2813 /****************************************************************************
2814 The guts of the mkdir command, split out so it may be called by the NT SMB
2816 ****************************************************************************/
2818 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2820 BOOL bad_path = False;
2821 SMB_STRUCT_STAT sbuf;
2824 unix_convert(directory,conn,0,&bad_path,&sbuf);
2826 if (check_name(directory, conn))
2827 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2830 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2831 if (!NT_STATUS_IS_OK(nterr))
2833 return map_nt_error_from_unix(errno);
2836 return NT_STATUS_OK;
2839 /****************************************************************************
2841 ****************************************************************************/
2843 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2848 START_PROFILE(SMBmkdir);
2850 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2852 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2854 status = mkdir_internal(conn, directory);
2855 if (!NT_STATUS_IS_OK(status))
2856 return ERROR_NT(status);
2858 outsize = set_message(outbuf,0,0,True);
2860 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2862 END_PROFILE(SMBmkdir);
2866 /****************************************************************************
2867 Static function used by reply_rmdir to delete an entire directory
2868 tree recursively. Return False on ok, True on fail.
2869 ****************************************************************************/
2871 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2873 const char *dname = NULL;
2875 void *dirptr = OpenDir(conn, directory, False);
2880 while((dname = ReadDirName(dirptr))) {
2884 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2887 /* Construct the full name. */
2888 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2894 pstrcpy(fullname, directory);
2895 pstrcat(fullname, "/");
2896 pstrcat(fullname, dname);
2898 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2903 if(st.st_mode & S_IFDIR) {
2904 if(recursive_rmdir(conn, fullname)!=0) {
2908 if(vfs_rmdir(conn,fullname) != 0) {
2912 } else if(vfs_unlink(conn,fullname) != 0) {
2921 /****************************************************************************
2922 The internals of the rmdir code - called elsewhere.
2923 ****************************************************************************/
2925 BOOL rmdir_internals(connection_struct *conn, char *directory)
2929 ok = (vfs_rmdir(conn,directory) == 0);
2930 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2932 * Check to see if the only thing in this directory are
2933 * vetoed files/directories. If so then delete them and
2934 * retry. If we fail to delete any of them (and we *don't*
2935 * do a recursive delete) then fail the rmdir.
2937 BOOL all_veto_files = True;
2939 void *dirptr = OpenDir(conn, directory, False);
2941 if(dirptr != NULL) {
2942 int dirpos = TellDir(dirptr);
2943 while ((dname = ReadDirName(dirptr))) {
2944 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2946 if(!IS_VETO_PATH(conn, dname)) {
2947 all_veto_files = False;
2952 if(all_veto_files) {
2953 SeekDir(dirptr,dirpos);
2954 while ((dname = ReadDirName(dirptr))) {
2958 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2961 /* Construct the full name. */
2962 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2967 pstrcpy(fullname, directory);
2968 pstrcat(fullname, "/");
2969 pstrcat(fullname, dname);
2971 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2973 if(st.st_mode & S_IFDIR) {
2974 if(lp_recursive_veto_delete(SNUM(conn))) {
2975 if(recursive_rmdir(conn, fullname) != 0)
2978 if(vfs_rmdir(conn,fullname) != 0)
2980 } else if(vfs_unlink(conn,fullname) != 0)
2984 /* Retry the rmdir */
2985 ok = (vfs_rmdir(conn,directory) == 0);
2995 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3000 /****************************************************************************
3002 ****************************************************************************/
3004 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3009 BOOL bad_path = False;
3010 SMB_STRUCT_STAT sbuf;
3011 START_PROFILE(SMBrmdir);
3013 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3015 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3017 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3019 if (check_name(directory,conn)) {
3020 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3021 ok = rmdir_internals(conn, directory);
3025 set_bad_path_error(errno, bad_path);
3026 END_PROFILE(SMBrmdir);
3027 return(UNIXERROR(ERRDOS,ERRbadpath));
3030 outsize = set_message(outbuf,0,0,True);
3032 DEBUG( 3, ( "rmdir %s\n", directory ) );
3034 END_PROFILE(SMBrmdir);
3038 /*******************************************************************
3039 Resolve wildcards in a filename rename.
3040 ********************************************************************/
3042 static BOOL resolve_wildcards(char *name1,char *name2)
3044 fstring root1,root2;
3048 name1 = strrchr_m(name1,'/');
3049 name2 = strrchr_m(name2,'/');
3051 if (!name1 || !name2)
3054 fstrcpy(root1,name1);
3055 fstrcpy(root2,name2);
3056 p = strrchr_m(root1,'.');
3063 p = strrchr_m(root2,'.');
3097 pstrcpy(name2,root2);
3100 pstrcat(name2,ext2);
3106 /****************************************************************************
3107 The guts of the rename command, split out so it may be called by the NT SMB
3109 ****************************************************************************/
3111 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3115 pstring newname_last_component;
3118 BOOL bad_path1 = False;
3119 BOOL bad_path2 = False;
3121 NTSTATUS error = NT_STATUS_OK;
3123 SMB_STRUCT_STAT sbuf1, sbuf2;
3125 *directory = *mask = 0;
3127 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3128 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3131 * Split the old name into directory and last component
3132 * strings. Note that unix_convert may have stripped off a
3133 * leading ./ from both name and newname if the rename is
3134 * at the root of the share. We need to make sure either both
3135 * name and newname contain a / character or neither of them do
3136 * as this is checked in resolve_wildcards().
3139 p = strrchr_m(name,'/');
3141 pstrcpy(directory,".");
3145 pstrcpy(directory,name);
3147 *p = '/'; /* Replace needed for exceptional test below. */
3151 * We should only check the mangled cache
3152 * here if unix_convert failed. This means
3153 * that the path in 'mask' doesn't exist
3154 * on the file system and so we need to look
3155 * for a possible mangle. This patch from
3156 * Tine Smukavec <valentin.smukavec@hermes.si>.
3159 if (!rc && mangle_is_mangled(mask))
3160 mangle_check_cache( mask );
3162 has_wild = ms_has_wild(mask);
3166 * No wildcards - just process the one file.
3168 BOOL is_short_name = mangle_is_8_3(name, True);
3170 /* Add a terminating '/' to the directory name. */
3171 pstrcat(directory,"/");
3172 pstrcat(directory,mask);
3174 /* Ensure newname contains a '/' also */
3175 if(strrchr_m(newname,'/') == 0) {
3178 pstrcpy(tmpstr, "./");
3179 pstrcat(tmpstr, newname);
3180 pstrcpy(newname, tmpstr);
3183 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3184 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3185 case_sensitive, case_preserve, short_case_preserve, directory,
3186 newname, newname_last_component, is_short_name));
3189 * Check for special case with case preserving and not
3190 * case sensitive, if directory and newname are identical,
3191 * and the old last component differs from the original
3192 * last component only by case, then we should allow
3193 * the rename (user is trying to change the case of the
3196 if((case_sensitive == False) &&
3197 (((case_preserve == True) &&
3198 (is_short_name == False)) ||
3199 ((short_case_preserve == True) &&
3200 (is_short_name == True))) &&
3201 strcsequal(directory, newname)) {
3202 pstring newname_modified_last_component;
3205 * Get the last component of the modified name.
3206 * Note that we guarantee that newname contains a '/'
3209 p = strrchr_m(newname,'/');
3210 pstrcpy(newname_modified_last_component,p+1);
3212 if(strcsequal(newname_modified_last_component,
3213 newname_last_component) == False) {
3215 * Replace the modified last component with
3218 pstrcpy(p+1, newname_last_component);
3222 resolve_wildcards(directory,newname);
3225 * The source object must exist.
3228 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3229 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3230 directory,newname));
3232 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3234 * Must return different errors depending on whether the parent
3235 * directory existed or not.
3238 p = strrchr_m(directory, '/');
3240 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3242 if (vfs_object_exist(conn, directory, NULL))
3243 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3244 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3246 error = map_nt_error_from_unix(errno);
3247 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3248 nt_errstr(error), directory,newname));
3253 error = can_rename(directory,conn,&sbuf1);
3255 if (!NT_STATUS_IS_OK(error)) {
3256 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3257 nt_errstr(error), directory,newname));
3262 * If the src and dest names are identical - including case,
3263 * don't do the rename, just return success.
3266 if (strcsequal(directory, newname)) {
3267 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3268 return NT_STATUS_OK;
3271 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3272 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3273 directory,newname));
3274 return NT_STATUS_OBJECT_NAME_COLLISION;
3277 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3278 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3279 directory,newname));
3280 return NT_STATUS_OK;
3283 if (errno == ENOTDIR || errno == EISDIR)
3284 error = NT_STATUS_OBJECT_NAME_COLLISION;
3286 error = map_nt_error_from_unix(errno);
3288 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3289 nt_errstr(error), directory,newname));
3294 * Wildcards - process each file that matches.
3296 void *dirptr = NULL;
3300 if (check_name(directory,conn))
3301 dirptr = OpenDir(conn, directory, True);
3304 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3306 if (strequal(mask,"????????.???"))
3309 while ((dname = ReadDirName(dirptr))) {
3312 pstrcpy(fname,dname);
3314 if(!mask_match(fname, mask, case_sensitive))
3317 error = NT_STATUS_ACCESS_DENIED;
3318 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3319 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3320 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3321 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3324 error = can_rename(fname,conn,&sbuf1);
3325 if (!NT_STATUS_IS_OK(error)) {
3326 DEBUG(6,("rename %s refused\n", fname));
3329 pstrcpy(destname,newname);
3331 if (!resolve_wildcards(fname,destname)) {
3332 DEBUG(6,("resolve_wildcards %s %s failed\n",
3337 if (!replace_if_exists &&
3338 vfs_file_exist(conn,destname, NULL)) {
3339 DEBUG(6,("file_exist %s\n", destname));
3340 error = NT_STATUS_OBJECT_NAME_COLLISION;
3344 if (!conn->vfs_ops.rename(conn,fname,destname))
3346 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3352 if (count == 0 && NT_STATUS_IS_OK(error)) {
3353 error = map_nt_error_from_unix(errno);
3359 /****************************************************************************
3361 ****************************************************************************/
3363 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3372 START_PROFILE(SMBmv);
3374 p = smb_buf(inbuf) + 1;
3375 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3377 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3379 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3380 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3382 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3384 status = rename_internals(conn, name, newname, False);
3385 if (!NT_STATUS_IS_OK(status)) {
3386 return ERROR_NT(status);
3390 * Win2k needs a changenotify request response before it will
3391 * update after a rename..
3393 process_pending_change_notify_queue((time_t)0);
3394 outsize = set_message(outbuf,0,0,True);
3400 /*******************************************************************
3401 Copy a file as part of a reply_copy.
3402 ******************************************************************/
3404 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3405 int count,BOOL target_is_directory, int *err_ret)
3408 SMB_STRUCT_STAT src_sbuf, sbuf2;
3410 files_struct *fsp1,*fsp2;
3415 pstrcpy(dest,dest1);
3416 if (target_is_directory) {
3417 char *p = strrchr_m(src,'/');
3426 if (!vfs_file_exist(conn,src,&src_sbuf))
3429 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3430 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3435 if (!target_is_directory && count)
3436 ofun = FILE_EXISTS_OPEN;
3438 if (vfs_stat(conn,dest,&sbuf2) == -1)
3439 ZERO_STRUCTP(&sbuf2);
3441 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3442 ofun,src_sbuf.st_mode,0,&Access,&action);
3445 close_file(fsp1,False);
3449 if ((ofun&3) == 1) {
3450 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3451 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3453 * Stop the copy from occurring.
3456 src_sbuf.st_size = 0;
3460 if (src_sbuf.st_size)
3461 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3463 close_file(fsp1,False);
3465 /* Ensure the modtime is set correctly on the destination file. */
3466 fsp2->pending_modtime = src_sbuf.st_mtime;
3469 * As we are opening fsp1 read-only we only expect
3470 * an error on close on fsp2 if we are out of space.
3471 * Thus we don't look at the error return from the
3474 *err_ret = close_file(fsp2,False);
3476 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3479 /****************************************************************************
3480 Reply to a file copy.
3481 ****************************************************************************/
3483 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3488 pstring mask,newname;
3491 int error = ERRnoaccess;
3495 int tid2 = SVAL(inbuf,smb_vwv0);
3496 int ofun = SVAL(inbuf,smb_vwv1);
3497 int flags = SVAL(inbuf,smb_vwv2);
3498 BOOL target_is_directory=False;
3499 BOOL bad_path1 = False;
3500 BOOL bad_path2 = False;
3502 SMB_STRUCT_STAT sbuf1, sbuf2;
3504 START_PROFILE(SMBcopy);
3506 *directory = *mask = 0;
3509 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3510 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3512 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3514 if (tid2 != conn->cnum) {
3515 /* can't currently handle inter share copies XXXX */
3516 DEBUG(3,("Rejecting inter-share copy\n"));
3517 END_PROFILE(SMBcopy);
3518 return ERROR_DOS(ERRSRV,ERRinvdevice);
3521 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3522 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3524 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3525 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3527 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3529 if ((flags&1) && target_is_directory) {
3530 END_PROFILE(SMBcopy);
3531 return ERROR_DOS(ERRDOS,ERRbadfile);
3534 if ((flags&2) && !target_is_directory) {
3535 END_PROFILE(SMBcopy);
3536 return ERROR_DOS(ERRDOS,ERRbadpath);
3539 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3540 /* wants a tree copy! XXXX */
3541 DEBUG(3,("Rejecting tree copy\n"));
3542 END_PROFILE(SMBcopy);
3543 return ERROR_DOS(ERRSRV,ERRerror);
3546 p = strrchr_m(name,'/');
3548 pstrcpy(directory,"./");
3552 pstrcpy(directory,name);
3557 * We should only check the mangled cache
3558 * here if unix_convert failed. This means
3559 * that the path in 'mask' doesn't exist
3560 * on the file system and so we need to look
3561 * for a possible mangle. This patch from
3562 * Tine Smukavec <valentin.smukavec@hermes.si>.
3565 if (!rc && mangle_is_mangled(mask))
3566 mangle_check_cache( mask );
3568 has_wild = ms_has_wild(mask);
3571 pstrcat(directory,"/");
3572 pstrcat(directory,mask);
3573 if (resolve_wildcards(directory,newname) &&
3574 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3578 END_PROFILE(SMBcopy);
3579 return(UNIXERROR(ERRHRD,ERRgeneral));
3582 exists = vfs_file_exist(conn,directory,NULL);
3585 void *dirptr = NULL;
3589 if (check_name(directory,conn))
3590 dirptr = OpenDir(conn, directory, True);
3595 if (strequal(mask,"????????.???"))
3598 while ((dname = ReadDirName(dirptr))) {
3600 pstrcpy(fname,dname);
3602 if(!mask_match(fname, mask, case_sensitive))
3605 error = ERRnoaccess;
3606 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3607 pstrcpy(destname,newname);
3608 if (resolve_wildcards(fname,destname) &&
3609 copy_file(fname,destname,conn,ofun,
3610 count,target_is_directory,&err))
3612 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3620 /* Error on close... */
3622 END_PROFILE(SMBcopy);
3623 return(UNIXERROR(ERRHRD,ERRgeneral));
3627 END_PROFILE(SMBcopy);
3628 return ERROR_DOS(ERRDOS,error);
3630 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3631 unix_ERR_class = ERRDOS;
3632 unix_ERR_code = ERRbadpath;
3634 END_PROFILE(SMBcopy);
3635 return(UNIXERROR(ERRDOS,error));
3639 outsize = set_message(outbuf,1,0,True);
3640 SSVAL(outbuf,smb_vwv0,count);
3642 END_PROFILE(SMBcopy);
3646 /****************************************************************************
3648 ****************************************************************************/
3650 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3657 START_PROFILE(pathworks_setdir);
3660 if (!CAN_SETDIR(snum)) {
3661 END_PROFILE(pathworks_setdir);
3662 return ERROR_DOS(ERRDOS,ERRnoaccess);
3665 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3667 if (strlen(newdir) == 0) {
3670 ok = vfs_directory_exist(conn,newdir,NULL);
3672 string_set(&conn->connectpath,newdir);
3676 END_PROFILE(pathworks_setdir);
3677 return ERROR_DOS(ERRDOS,ERRbadpath);
3680 outsize = set_message(outbuf,0,0,True);
3681 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3683 DEBUG(3,("setdir %s\n", newdir));
3685 END_PROFILE(pathworks_setdir);
3689 /****************************************************************************
3690 Get a lock pid, dealing with large count requests.
3691 ****************************************************************************/
3693 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3695 if(!large_file_format)
3696 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3698 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3701 /****************************************************************************
3702 Get a lock count, dealing with large count requests.
3703 ****************************************************************************/
3705 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3707 SMB_BIG_UINT count = 0;
3709 if(!large_file_format) {
3710 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3713 #if defined(HAVE_LONGLONG)
3714 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3715 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3716 #else /* HAVE_LONGLONG */
3719 * NT4.x seems to be broken in that it sends large file (64 bit)
3720 * lockingX calls even if the CAP_LARGE_FILES was *not*
3721 * negotiated. For boxes without large unsigned ints truncate the
3722 * lock count by dropping the top 32 bits.
3725 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3726 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3727 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3728 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3729 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3732 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3733 #endif /* HAVE_LONGLONG */
3739 #if !defined(HAVE_LONGLONG)
3740 /****************************************************************************
3741 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3742 ****************************************************************************/
3744 static uint32 map_lock_offset(uint32 high, uint32 low)
3748 uint32 highcopy = high;
3751 * Try and find out how many significant bits there are in high.
3754 for(i = 0; highcopy; i++)
3758 * We use 31 bits not 32 here as POSIX
3759 * lock offsets may not be negative.
3762 mask = (~0) << (31 - i);
3765 return 0; /* Fail. */
3771 #endif /* !defined(HAVE_LONGLONG) */
3773 /****************************************************************************
3774 Get a lock offset, dealing with large offset requests.
3775 ****************************************************************************/
3777 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3779 SMB_BIG_UINT offset = 0;
3783 if(!large_file_format) {
3784 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3787 #if defined(HAVE_LONGLONG)
3788 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3789 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3790 #else /* HAVE_LONGLONG */
3793 * NT4.x seems to be broken in that it sends large file (64 bit)
3794 * lockingX calls even if the CAP_LARGE_FILES was *not*
3795 * negotiated. For boxes without large unsigned ints mangle the
3796 * lock offset by mapping the top 32 bits onto the lower 32.
3799 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3800 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3801 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3804 if((new_low = map_lock_offset(high, low)) == 0) {
3806 return (SMB_BIG_UINT)-1;
3809 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3810 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3811 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3812 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3815 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3816 #endif /* HAVE_LONGLONG */
3822 /****************************************************************************
3823 Reply to a lockingX request.
3824 ****************************************************************************/
3826 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3828 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3829 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3830 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3831 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3832 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3833 SMB_BIG_UINT count = 0, offset = 0;
3835 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3838 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3842 START_PROFILE(SMBlockingX);
3844 CHECK_FSP(fsp,conn);
3846 data = smb_buf(inbuf);
3848 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3849 /* we don't support these - and CANCEL_LOCK makes w2k
3850 and XP reboot so I don't really want to be
3851 compatible! (tridge) */
3852 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3855 /* Check if this is an oplock break on a file
3856 we have granted an oplock on.
3858 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3859 /* Client can insist on breaking to none. */
3860 BOOL break_to_none = (oplocklevel == 0);
3862 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3863 (unsigned int)oplocklevel, fsp->fnum ));
3866 * Make sure we have granted an exclusive or batch oplock on this file.
3869 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3870 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3871 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3873 /* if this is a pure oplock break request then don't send a reply */
3874 if (num_locks == 0 && num_ulocks == 0) {
3875 END_PROFILE(SMBlockingX);
3878 END_PROFILE(SMBlockingX);
3879 return ERROR_DOS(ERRDOS,ERRlock);
3883 if (remove_oplock(fsp, break_to_none) == False) {
3884 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3888 /* if this is a pure oplock break request then don't send a reply */
3889 if (num_locks == 0 && num_ulocks == 0) {
3890 /* Sanity check - ensure a pure oplock break is not a
3892 if(CVAL(inbuf,smb_vwv0) != 0xff)
3893 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3894 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3895 END_PROFILE(SMBlockingX);
3901 * We do this check *after* we have checked this is not a oplock break
3902 * response message. JRA.
3905 release_level_2_oplocks_on_change(fsp);
3907 /* Data now points at the beginning of the list
3908 of smb_unlkrng structs */
3909 for(i = 0; i < (int)num_ulocks; i++) {
3910 lock_pid = get_lock_pid( data, i, large_file_format);
3911 count = get_lock_count( data, i, large_file_format);
3912 offset = get_lock_offset( data, i, large_file_format, &err);
3915 * There is no error code marked "stupid client bug".... :-).
3918 END_PROFILE(SMBlockingX);
3919 return ERROR_DOS(ERRDOS,ERRnoaccess);
3922 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3923 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3925 status = do_unlock(fsp,conn,lock_pid,count,offset);
3926 if (NT_STATUS_V(status)) {
3927 END_PROFILE(SMBlockingX);
3928 return ERROR_NT(status);
3932 /* Setup the timeout in seconds. */
3934 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3936 /* Now do any requested locks */
3937 data += ((large_file_format ? 20 : 10)*num_ulocks);
3939 /* Data now points at the beginning of the list
3940 of smb_lkrng structs */
3942 for(i = 0; i < (int)num_locks; i++) {
3943 lock_pid = get_lock_pid( data, i, large_file_format);
3944 count = get_lock_count( data, i, large_file_format);
3945 offset = get_lock_offset( data, i, large_file_format, &err);
3948 * There is no error code marked "stupid client bug".... :-).
3951 END_PROFILE(SMBlockingX);
3952 return ERROR_DOS(ERRDOS,ERRnoaccess);
3955 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3956 (double)offset, (double)count, (unsigned int)lock_pid,
3957 fsp->fsp_name, (int)lock_timeout ));
3959 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3960 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3961 if (NT_STATUS_V(status)) {
3962 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3964 * A blocking lock was requested. Package up
3965 * this smb into a queued request and push it
3966 * onto the blocking lock queue.
3968 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
3969 END_PROFILE(SMBlockingX);
3977 /* If any of the above locks failed, then we must unlock
3978 all of the previous locks (X/Open spec). */
3979 if (i != num_locks && num_locks != 0) {
3981 * Ensure we don't do a remove on the lock that just failed,
3982 * as under POSIX rules, if we have a lock already there, we
3983 * will delete it (and we shouldn't) .....
3985 for(i--; i >= 0; i--) {
3986 lock_pid = get_lock_pid( data, i, large_file_format);
3987 count = get_lock_count( data, i, large_file_format);
3988 offset = get_lock_offset( data, i, large_file_format, &err);
3991 * There is no error code marked "stupid client bug".... :-).
3994 END_PROFILE(SMBlockingX);
3995 return ERROR_DOS(ERRDOS,ERRnoaccess);
3998 do_unlock(fsp,conn,lock_pid,count,offset);
4000 END_PROFILE(SMBlockingX);
4001 return ERROR_NT(status);
4004 set_message(outbuf,2,0,True);
4006 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4007 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4009 END_PROFILE(SMBlockingX);
4010 return chain_reply(inbuf,outbuf,length,bufsize);
4013 /****************************************************************************
4014 Reply to a SMBreadbmpx (read block multiplex) request.
4015 ****************************************************************************/
4017 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4028 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4029 START_PROFILE(SMBreadBmpx);
4031 /* this function doesn't seem to work - disable by default */
4032 if (!lp_readbmpx()) {
4033 END_PROFILE(SMBreadBmpx);
4034 return ERROR_DOS(ERRSRV,ERRuseSTD);
4037 outsize = set_message(outbuf,8,0,True);
4039 CHECK_FSP(fsp,conn);
4042 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4043 maxcount = SVAL(inbuf,smb_vwv3);
4045 data = smb_buf(outbuf);
4046 pad = ((long)data)%4;
4051 max_per_packet = bufsize-(outsize+pad);
4055 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4056 END_PROFILE(SMBreadBmpx);
4057 return ERROR_DOS(ERRDOS,ERRlock);
4061 size_t N = MIN(max_per_packet,tcount-total_read);
4063 nread = read_file(fsp,data,startpos,N);
4068 if (nread < (ssize_t)N)
4069 tcount = total_read + nread;
4071 set_message(outbuf,8,nread,False);
4072 SIVAL(outbuf,smb_vwv0,startpos);
4073 SSVAL(outbuf,smb_vwv2,tcount);
4074 SSVAL(outbuf,smb_vwv6,nread);
4075 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4077 if (!send_smb(smbd_server_fd(),outbuf))
4078 exit_server("reply_readbmpx: send_smb failed.");
4080 total_read += nread;
4082 } while (total_read < (ssize_t)tcount);
4084 END_PROFILE(SMBreadBmpx);
4088 /****************************************************************************
4089 Reply to a SMBsetattrE.
4090 ****************************************************************************/
4092 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4094 struct utimbuf unix_times;
4096 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4097 START_PROFILE(SMBsetattrE);
4099 outsize = set_message(outbuf,0,0,True);
4101 if(!fsp || (fsp->conn != conn)) {
4102 END_PROFILE(SMBgetattrE);
4103 return ERROR_DOS(ERRDOS,ERRbadfid);
4107 * Convert the DOS times into unix times. Ignore create
4108 * time as UNIX can't set this.
4111 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4112 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4115 * Patch from Ray Frush <frush@engr.colostate.edu>
4116 * Sometimes times are sent as zero - ignore them.
4119 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4120 /* Ignore request */
4121 if( DEBUGLVL( 3 ) ) {
4122 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4123 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4125 END_PROFILE(SMBsetattrE);
4127 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4128 /* set modify time = to access time if modify time was 0 */
4129 unix_times.modtime = unix_times.actime;
4132 /* Set the date on this file */
4133 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4134 END_PROFILE(SMBsetattrE);
4135 return ERROR_DOS(ERRDOS,ERRnoaccess);
4138 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4139 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4141 END_PROFILE(SMBsetattrE);
4146 /* Back from the dead for OS/2..... JRA. */
4148 /****************************************************************************
4149 Reply to a SMBwritebmpx (write block multiplex primary) request.
4150 ****************************************************************************/
4152 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4155 ssize_t nwritten = -1;
4162 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4163 START_PROFILE(SMBwriteBmpx);
4165 CHECK_FSP(fsp,conn);
4169 tcount = SVAL(inbuf,smb_vwv1);
4170 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4171 write_through = BITSETW(inbuf+smb_vwv7,0);
4172 numtowrite = SVAL(inbuf,smb_vwv10);
4173 smb_doff = SVAL(inbuf,smb_vwv11);
4175 data = smb_base(inbuf) + smb_doff;
4177 /* If this fails we need to send an SMBwriteC response,
4178 not an SMBwritebmpx - set this up now so we don't forget */
4179 SCVAL(outbuf,smb_com,SMBwritec);
4181 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4182 END_PROFILE(SMBwriteBmpx);
4183 return(ERROR_DOS(ERRDOS,ERRlock));
4186 nwritten = write_file(fsp,data,startpos,numtowrite);
4188 if(lp_syncalways(SNUM(conn)) || write_through)
4189 sync_file(conn,fsp);
4191 if(nwritten < (ssize_t)numtowrite) {
4192 END_PROFILE(SMBwriteBmpx);
4193 return(UNIXERROR(ERRHRD,ERRdiskfull));
4196 /* If the maximum to be written to this file
4197 is greater than what we just wrote then set
4198 up a secondary struct to be attached to this
4199 fd, we will use this to cache error messages etc. */
4201 if((ssize_t)tcount > nwritten) {
4202 write_bmpx_struct *wbms;
4203 if(fsp->wbmpx_ptr != NULL)
4204 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4206 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4208 DEBUG(0,("Out of memory in reply_readmpx\n"));
4209 END_PROFILE(SMBwriteBmpx);
4210 return(ERROR_DOS(ERRSRV,ERRnoresource));
4212 wbms->wr_mode = write_through;
4213 wbms->wr_discard = False; /* No errors yet */
4214 wbms->wr_total_written = nwritten;
4215 wbms->wr_errclass = 0;
4217 fsp->wbmpx_ptr = wbms;
4220 /* We are returning successfully, set the message type back to
4222 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4224 outsize = set_message(outbuf,1,0,True);
4226 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4228 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4229 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4231 if (write_through && tcount==nwritten) {
4232 /* We need to send both a primary and a secondary response */
4233 smb_setlen(outbuf,outsize - 4);
4234 if (!send_smb(smbd_server_fd(),outbuf))
4235 exit_server("reply_writebmpx: send_smb failed.");
4237 /* Now the secondary */
4238 outsize = set_message(outbuf,1,0,True);
4239 SCVAL(outbuf,smb_com,SMBwritec);
4240 SSVAL(outbuf,smb_vwv0,nwritten);
4243 END_PROFILE(SMBwriteBmpx);
4247 /****************************************************************************
4248 Reply to a SMBwritebs (write block multiplex secondary) request.
4249 ****************************************************************************/
4251 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4254 ssize_t nwritten = -1;
4261 write_bmpx_struct *wbms;
4262 BOOL send_response = False;
4263 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4264 START_PROFILE(SMBwriteBs);
4266 CHECK_FSP(fsp,conn);
4269 tcount = SVAL(inbuf,smb_vwv1);
4270 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4271 numtowrite = SVAL(inbuf,smb_vwv6);
4272 smb_doff = SVAL(inbuf,smb_vwv7);
4274 data = smb_base(inbuf) + smb_doff;
4276 /* We need to send an SMBwriteC response, not an SMBwritebs */
4277 SCVAL(outbuf,smb_com,SMBwritec);
4279 /* This fd should have an auxiliary struct attached,
4280 check that it does */
4281 wbms = fsp->wbmpx_ptr;
4283 END_PROFILE(SMBwriteBs);
4287 /* If write through is set we can return errors, else we must cache them */
4288 write_through = wbms->wr_mode;
4290 /* Check for an earlier error */
4291 if(wbms->wr_discard) {
4292 END_PROFILE(SMBwriteBs);
4293 return -1; /* Just discard the packet */
4296 nwritten = write_file(fsp,data,startpos,numtowrite);
4298 if(lp_syncalways(SNUM(conn)) || write_through)
4299 sync_file(conn,fsp);
4301 if (nwritten < (ssize_t)numtowrite) {
4303 /* We are returning an error - we can delete the aux struct */
4306 fsp->wbmpx_ptr = NULL;
4307 END_PROFILE(SMBwriteBs);
4308 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4310 END_PROFILE(SMBwriteBs);
4311 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4314 /* Increment the total written, if this matches tcount
4315 we can discard the auxiliary struct (hurrah !) and return a writeC */
4316 wbms->wr_total_written += nwritten;
4317 if(wbms->wr_total_written >= tcount) {
4318 if (write_through) {
4319 outsize = set_message(outbuf,1,0,True);
4320 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4321 send_response = True;
4325 fsp->wbmpx_ptr = NULL;
4329 END_PROFILE(SMBwriteBs);
4333 END_PROFILE(SMBwriteBs);
4337 /****************************************************************************
4338 Reply to a SMBgetattrE.
4339 ****************************************************************************/
4341 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4343 SMB_STRUCT_STAT sbuf;
4346 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4347 START_PROFILE(SMBgetattrE);
4349 outsize = set_message(outbuf,11,0,True);
4351 if(!fsp || (fsp->conn != conn)) {
4352 END_PROFILE(SMBgetattrE);
4353 return ERROR_DOS(ERRDOS,ERRbadfid);
4356 /* Do an fstat on this file */
4357 if(fsp_stat(fsp, &sbuf)) {
4358 END_PROFILE(SMBgetattrE);
4359 return(UNIXERROR(ERRDOS,ERRnoaccess));
4362 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4365 * Convert the times into dos times. Set create
4366 * date to be last modify date as UNIX doesn't save
4370 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4371 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4372 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4375 SIVAL(outbuf,smb_vwv6,0);
4376 SIVAL(outbuf,smb_vwv8,0);
4378 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4379 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4381 SSVAL(outbuf,smb_vwv10, mode);
4383 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4385 END_PROFILE(SMBgetattrE);