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);
91 set_remote_machine_name(name2);
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), 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 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
276 set_message(outbuf,3,0,True);
279 p += srvstr_push(outbuf, p, devicename, -1,
280 STR_TERMINATE|STR_ASCII);
281 p += srvstr_push(outbuf, p, fsname, -1,
284 set_message_end(outbuf,p);
286 /* what does setting this bit do? It is set by NT4 and
287 may affect the ability to autorun mounted cdroms */
288 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
289 (lp_csc_policy(SNUM(conn)) << 2));
291 init_dfsroot(conn, inbuf, outbuf);
295 DEBUG(3,("tconX service=%s \n",
298 /* set the incoming and outgoing tid to the just created one */
299 SSVAL(inbuf,smb_tid,conn->cnum);
300 SSVAL(outbuf,smb_tid,conn->cnum);
302 END_PROFILE(SMBtconX);
303 return chain_reply(inbuf,outbuf,length,bufsize);
306 /****************************************************************************
307 Reply to an unknown type.
308 ****************************************************************************/
310 int reply_unknown(char *inbuf,char *outbuf)
313 type = CVAL(inbuf,smb_com);
315 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
316 smb_fn_name(type), type, type));
318 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
321 /****************************************************************************
323 ****************************************************************************/
325 int reply_ioctl(connection_struct *conn,
326 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
328 uint16 device = SVAL(inbuf,smb_vwv1);
329 uint16 function = SVAL(inbuf,smb_vwv2);
330 uint32 ioctl_code = (device << 16) + function;
331 int replysize, outsize;
333 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
334 START_PROFILE(SMBioctl);
336 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
338 switch (ioctl_code) {
339 case IOCTL_QUERY_JOB_INFO:
343 END_PROFILE(SMBioctl);
344 return(ERROR_DOS(ERRSRV,ERRnosupport));
347 outsize = set_message(outbuf,8,replysize+1,True);
348 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
349 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
350 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
351 p = smb_buf(outbuf) + 1; /* Allow for alignment */
353 switch (ioctl_code) {
354 case IOCTL_QUERY_JOB_INFO:
356 uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
357 SSVAL(p,0,rap_jobid); /* Job number */
358 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
359 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
364 END_PROFILE(SMBioctl);
368 /****************************************************************************
370 ****************************************************************************/
372 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
378 BOOL bad_path = False;
379 SMB_STRUCT_STAT sbuf;
380 START_PROFILE(SMBchkpth);
382 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
384 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
386 unix_convert(name,conn,0,&bad_path,&sbuf);
388 mode = SVAL(inbuf,smb_vwv0);
390 if (check_name(name,conn)) {
391 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
392 ok = S_ISDIR(sbuf.st_mode);
396 /* We special case this - as when a Windows machine
397 is parsing a path is steps through the components
398 one at a time - if a component fails it expects
399 ERRbadpath, not ERRbadfile.
402 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
404 return(UNIXERROR(ERRDOS,ERRbadpath));
407 outsize = set_message(outbuf,0,0,True);
409 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
411 END_PROFILE(SMBchkpth);
415 /****************************************************************************
417 ****************************************************************************/
419 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
423 SMB_STRUCT_STAT sbuf;
428 BOOL bad_path = False;
430 START_PROFILE(SMBgetatr);
432 p = smb_buf(inbuf) + 1;
433 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
435 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
437 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
438 under WfWg - weird! */
441 mode = aHIDDEN | aDIR;
442 if (!CAN_WRITE(conn)) mode |= aRONLY;
449 unix_convert(fname,conn,0,&bad_path,&sbuf);
450 if (check_name(fname,conn))
452 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
454 mode = dos_mode(conn,fname,&sbuf);
456 mtime = sbuf.st_mtime;
462 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
468 set_bad_path_error(errno, bad_path);
469 END_PROFILE(SMBgetatr);
470 return(UNIXERROR(ERRDOS,ERRbadfile));
473 outsize = set_message(outbuf,10,0,True);
475 SSVAL(outbuf,smb_vwv0,mode);
476 if(lp_dos_filetime_resolution(SNUM(conn)) )
477 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
479 put_dos_date3(outbuf,smb_vwv1,mtime);
480 SIVAL(outbuf,smb_vwv3,(uint32)size);
482 if (Protocol >= PROTOCOL_NT1)
483 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
485 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
487 END_PROFILE(SMBgetatr);
491 /****************************************************************************
493 ****************************************************************************/
495 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
502 SMB_STRUCT_STAT sbuf;
503 BOOL bad_path = False;
506 START_PROFILE(SMBsetatr);
508 p = smb_buf(inbuf) + 1;
509 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
510 unix_convert(fname,conn,0,&bad_path,&sbuf);
512 mode = SVAL(inbuf,smb_vwv0);
513 mtime = make_unix_date3(inbuf+smb_vwv1);
515 if (VALID_STAT_OF_DIR(sbuf))
520 if (check_name(fname,conn))
521 ok = (file_chmod(conn,fname,mode,NULL) == 0);
523 ok = set_filetime(conn,fname,mtime);
527 set_bad_path_error(errno, bad_path);
528 END_PROFILE(SMBsetatr);
529 return(UNIXERROR(ERRDOS,ERRnoaccess));
532 outsize = set_message(outbuf,0,0,True);
534 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
536 END_PROFILE(SMBsetatr);
540 /****************************************************************************
542 ****************************************************************************/
544 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
547 SMB_BIG_UINT dfree,dsize,bsize;
548 START_PROFILE(SMBdskattr);
550 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
552 outsize = set_message(outbuf,5,0,True);
554 if (Protocol <= PROTOCOL_LANMAN2) {
555 double total_space, free_space;
556 /* we need to scale this to a number that DOS6 can handle. We
557 use floating point so we can handle large drives on systems
558 that don't have 64 bit integers
560 we end up displaying a maximum of 2G to DOS systems
562 total_space = dsize * (double)bsize;
563 free_space = dfree * (double)bsize;
565 dsize = (total_space+63*512) / (64*512);
566 dfree = (free_space+63*512) / (64*512);
568 if (dsize > 0xFFFF) dsize = 0xFFFF;
569 if (dfree > 0xFFFF) dfree = 0xFFFF;
571 SSVAL(outbuf,smb_vwv0,dsize);
572 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
573 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
574 SSVAL(outbuf,smb_vwv3,dfree);
576 SSVAL(outbuf,smb_vwv0,dsize);
577 SSVAL(outbuf,smb_vwv1,bsize/512);
578 SSVAL(outbuf,smb_vwv2,512);
579 SSVAL(outbuf,smb_vwv3,dfree);
582 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
584 END_PROFILE(SMBdskattr);
588 /****************************************************************************
590 Can be called from SMBsearch, SMBffirst or SMBfunique.
591 ****************************************************************************/
593 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
604 BOOL finished = False;
613 BOOL check_descend = False;
614 BOOL expect_close = False;
615 BOOL can_open = True;
616 BOOL bad_path = False;
617 START_PROFILE(SMBsearch);
619 *mask = *directory = *fname = 0;
621 /* If we were called as SMBffirst then we must expect close. */
622 if(CVAL(inbuf,smb_com) == SMBffirst)
625 outsize = set_message(outbuf,1,3,True);
626 maxentries = SVAL(inbuf,smb_vwv0);
627 dirtype = SVAL(inbuf,smb_vwv1);
628 p = smb_buf(inbuf) + 1;
629 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
631 status_len = SVAL(p, 0);
634 /* dirtype &= ~aDIR; */
638 SMB_STRUCT_STAT sbuf;
641 pstrcpy(directory,path);
643 unix_convert(directory,conn,0,&bad_path,&sbuf);
646 if (!check_name(directory,conn))
649 p = strrchr_m(dir2,'/');
661 p = strrchr_m(directory,'/');
667 if (strlen(directory) == 0)
668 pstrcpy(directory,"./");
669 memset((char *)status,'\0',21);
670 SCVAL(status,0,(dirtype & 0x1F));
676 status_dirtype = CVAL(status,0) & 0x1F;
677 if (status_dirtype != (dirtype & 0x1F))
678 dirtype = status_dirtype;
680 conn->dirptr = dptr_fetch(status+12,&dptr_num);
683 string_set(&conn->dirpath,dptr_path(dptr_num));
684 fstrcpy(mask, dptr_wcard(dptr_num));
689 p = smb_buf(outbuf) + 3;
695 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
700 set_bad_path_error(errno, bad_path);
701 END_PROFILE(SMBsearch);
702 return (UNIXERROR(ERRDOS,ERRnofids));
704 END_PROFILE(SMBsearch);
705 return ERROR_DOS(ERRDOS,ERRnofids);
707 dptr_set_wcard(dptr_num, strdup(mask));
710 DEBUG(4,("dptr_num is %d\n",dptr_num));
714 if ((dirtype&0x1F) == aVOLID)
717 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
718 dptr_fill(p+12,dptr_num);
719 if (dptr_zero(p+12) && (status_len==0))
723 p += DIR_STRUCT_SIZE;
727 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
728 conn->dirpath,lp_dontdescend(SNUM(conn))));
729 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
730 check_descend = True;
732 for (i=numentries;(i<maxentries) && !finished;i++)
735 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
739 make_dir_struct(p,mask,fname,size,mode,date);
740 dptr_fill(p+12,dptr_num);
743 p += DIR_STRUCT_SIZE;
752 if (numentries == 0 || !ok)
754 SCVAL(outbuf,smb_rcls,ERRDOS);
755 SSVAL(outbuf,smb_err,ERRnofiles);
756 dptr_close(&dptr_num);
759 /* If we were called as SMBffirst with smb_search_id == NULL
760 and no entries were found then return error and close dirptr
763 if(ok && expect_close && numentries == 0 && status_len == 0)
765 SCVAL(outbuf,smb_rcls,ERRDOS);
766 SSVAL(outbuf,smb_err,ERRnofiles);
767 /* Also close the dptr - we know it's gone */
768 dptr_close(&dptr_num);
771 /* If we were called as SMBfunique, then we can close the dirptr now ! */
772 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
773 dptr_close(&dptr_num);
775 SSVAL(outbuf,smb_vwv0,numentries);
776 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
777 SCVAL(smb_buf(outbuf),0,5);
778 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
780 if (Protocol >= PROTOCOL_NT1)
781 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
783 outsize += DIR_STRUCT_SIZE*numentries;
784 smb_setlen(outbuf,outsize - 4);
786 if ((! *directory) && dptr_path(dptr_num))
787 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
789 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
790 smb_fn_name(CVAL(inbuf,smb_com)),
791 mask, directory, dirtype, numentries, maxentries ) );
793 END_PROFILE(SMBsearch);
797 /****************************************************************************
798 Reply to a fclose (stop directory search).
799 ****************************************************************************/
801 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
810 START_PROFILE(SMBfclose);
812 outsize = set_message(outbuf,1,0,True);
813 p = smb_buf(inbuf) + 1;
814 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
816 status_len = SVAL(p,0);
819 if (status_len == 0) {
820 END_PROFILE(SMBfclose);
821 return ERROR_DOS(ERRSRV,ERRsrverror);
826 if(dptr_fetch(status+12,&dptr_num)) {
827 /* Close the dptr - we know it's gone */
828 dptr_close(&dptr_num);
831 SSVAL(outbuf,smb_vwv0,0);
833 DEBUG(3,("search close\n"));
835 END_PROFILE(SMBfclose);
839 /****************************************************************************
841 ****************************************************************************/
843 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
853 SMB_STRUCT_STAT sbuf;
854 BOOL bad_path = False;
856 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
857 START_PROFILE(SMBopen);
859 share_mode = SVAL(inbuf,smb_vwv0);
861 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
863 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
865 unix_convert(fname,conn,0,&bad_path,&sbuf);
867 unixmode = unix_mode(conn,aARCH,fname);
869 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
870 unixmode, oplock_request,&rmode,NULL);
874 set_bad_path_error(errno, bad_path);
875 END_PROFILE(SMBopen);
876 return(UNIXERROR(ERRDOS,ERRnoaccess));
880 fmode = dos_mode(conn,fname,&sbuf);
881 mtime = sbuf.st_mtime;
884 DEBUG(3,("attempt to open a directory %s\n",fname));
885 close_file(fsp,False);
886 END_PROFILE(SMBopen);
887 return ERROR_DOS(ERRDOS,ERRnoaccess);
890 outsize = set_message(outbuf,7,0,True);
891 SSVAL(outbuf,smb_vwv0,fsp->fnum);
892 SSVAL(outbuf,smb_vwv1,fmode);
893 if(lp_dos_filetime_resolution(SNUM(conn)) )
894 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
896 put_dos_date3(outbuf,smb_vwv2,mtime);
897 SIVAL(outbuf,smb_vwv4,(uint32)size);
898 SSVAL(outbuf,smb_vwv6,rmode);
900 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
901 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
904 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
905 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
906 END_PROFILE(SMBopen);
910 /****************************************************************************
911 Reply to an open and X.
912 ****************************************************************************/
914 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
917 int smb_mode = SVAL(inbuf,smb_vwv3);
918 int smb_attr = SVAL(inbuf,smb_vwv5);
919 /* Breakout the oplock request bits so we can set the
920 reply bits separately. */
921 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
922 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
923 BOOL oplock_request = ex_oplock_request | core_oplock_request;
925 int open_flags = SVAL(inbuf,smb_vwv2);
926 int smb_sattr = SVAL(inbuf,smb_vwv4);
927 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
929 int smb_ofun = SVAL(inbuf,smb_vwv8);
932 int fmode=0,mtime=0,rmode=0;
933 SMB_STRUCT_STAT sbuf;
935 BOOL bad_path = False;
937 START_PROFILE(SMBopenX);
939 /* If it's an IPC, pass off the pipe handler. */
941 if (lp_nt_pipe_support()) {
942 END_PROFILE(SMBopenX);
943 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
945 END_PROFILE(SMBopenX);
946 return ERROR_DOS(ERRSRV,ERRaccess);
950 /* XXXX we need to handle passed times, sattr and flags */
951 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
953 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
955 unix_convert(fname,conn,0,&bad_path,&sbuf);
957 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
959 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
960 oplock_request, &rmode,&smb_action);
964 set_bad_path_error(errno, bad_path);
965 END_PROFILE(SMBopenX);
966 return(UNIXERROR(ERRDOS,ERRnoaccess));
970 fmode = dos_mode(conn,fname,&sbuf);
971 mtime = sbuf.st_mtime;
973 close_file(fsp,False);
974 END_PROFILE(SMBopenX);
975 return ERROR_DOS(ERRDOS,ERRnoaccess);
978 /* If the caller set the extended oplock request bit
979 and we granted one (by whatever means) - set the
980 correct bit for extended oplock reply.
983 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
984 smb_action |= EXTENDED_OPLOCK_GRANTED;
987 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
988 smb_action |= EXTENDED_OPLOCK_GRANTED;
991 /* If the caller set the core oplock request bit
992 and we granted one (by whatever means) - set the
993 correct bit for core oplock reply.
996 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
997 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1000 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1001 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1004 set_message(outbuf,15,0,True);
1005 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1006 SSVAL(outbuf,smb_vwv3,fmode);
1007 if(lp_dos_filetime_resolution(SNUM(conn)) )
1008 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1010 put_dos_date3(outbuf,smb_vwv4,mtime);
1011 SIVAL(outbuf,smb_vwv6,(uint32)size);
1012 SSVAL(outbuf,smb_vwv8,rmode);
1013 SSVAL(outbuf,smb_vwv11,smb_action);
1015 END_PROFILE(SMBopenX);
1016 return chain_reply(inbuf,outbuf,length,bufsize);
1019 /****************************************************************************
1020 Reply to a SMBulogoffX.
1021 ****************************************************************************/
1023 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1025 uint16 vuid = SVAL(inbuf,smb_uid);
1026 user_struct *vuser = get_valid_user_struct(vuid);
1027 START_PROFILE(SMBulogoffX);
1030 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1033 /* in user level security we are supposed to close any files
1034 open by this user */
1035 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1036 file_close_user(vuid);
1039 invalidate_vuid(vuid);
1041 set_message(outbuf,2,0,True);
1043 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1045 END_PROFILE(SMBulogoffX);
1046 return chain_reply(inbuf,outbuf,length,bufsize);
1049 /****************************************************************************
1050 Reply to a mknew or a create.
1051 ****************************************************************************/
1053 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1061 BOOL bad_path = False;
1063 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1064 SMB_STRUCT_STAT sbuf;
1065 START_PROFILE(SMBcreate);
1067 com = SVAL(inbuf,smb_com);
1069 createmode = SVAL(inbuf,smb_vwv0);
1070 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1072 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1074 unix_convert(fname,conn,0,&bad_path,&sbuf);
1076 if (createmode & aVOLID) {
1077 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1080 unixmode = unix_mode(conn,createmode,fname);
1084 /* We should fail if file exists. */
1085 ofun = FILE_CREATE_IF_NOT_EXIST;
1089 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1090 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1093 /* Open file in dos compatibility share mode. */
1094 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1095 ofun, unixmode, oplock_request, NULL, NULL);
1099 set_bad_path_error(errno, bad_path);
1100 END_PROFILE(SMBcreate);
1101 return(UNIXERROR(ERRDOS,ERRnoaccess));
1104 outsize = set_message(outbuf,1,0,True);
1105 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1107 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1108 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1111 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1112 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1114 DEBUG( 2, ( "new file %s\n", fname ) );
1115 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1116 fname, fsp->fd, createmode, (int)unixmode ) );
1118 END_PROFILE(SMBcreate);
1122 /****************************************************************************
1123 Reply to a create temporary file.
1124 ****************************************************************************/
1126 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1132 BOOL bad_path = False;
1134 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1136 SMB_STRUCT_STAT sbuf;
1139 START_PROFILE(SMBctemp);
1141 createmode = SVAL(inbuf,smb_vwv0);
1142 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1143 pstrcat(fname,"\\TMXXXXXX");
1145 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1147 unix_convert(fname,conn,0,&bad_path,&sbuf);
1149 unixmode = unix_mode(conn,createmode,fname);
1151 tmpfd = smb_mkstemp(fname);
1153 END_PROFILE(SMBctemp);
1154 return(UNIXERROR(ERRDOS,ERRnoaccess));
1157 vfs_stat(conn,fname,&sbuf);
1159 /* Open file in dos compatibility share mode. */
1160 /* We should fail if file does not exist. */
1161 fsp = open_file_shared(conn,fname,&sbuf,
1162 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1163 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1164 unixmode, oplock_request, NULL, NULL);
1166 /* close fd from smb_mkstemp() */
1170 set_bad_path_error(errno, bad_path);
1171 END_PROFILE(SMBctemp);
1172 return(UNIXERROR(ERRDOS,ERRnoaccess));
1175 outsize = set_message(outbuf,1,0,True);
1176 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1178 /* the returned filename is relative to the directory */
1179 s = strrchr_m(fname, '/');
1186 p = smb_buf(outbuf);
1187 SSVALS(p, 0, -1); /* what is this? not in spec */
1188 SSVAL(p, 2, strlen(s));
1190 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1191 outsize = set_message_end(outbuf, p);
1193 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1194 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1197 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1198 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1200 DEBUG( 2, ( "created temp file %s\n", fname ) );
1201 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1202 fname, fsp->fd, createmode, (int)unixmode ) );
1204 END_PROFILE(SMBctemp);
1208 /*******************************************************************
1209 Check if a user is allowed to rename a file.
1210 ********************************************************************/
1212 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1218 if (!CAN_WRITE(conn))
1219 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1221 if (S_ISDIR(pst->st_mode))
1222 return NT_STATUS_OK;
1224 /* We need a better way to return NT status codes from open... */
1228 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1229 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1232 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1233 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1234 ret = NT_STATUS_SHARING_VIOLATION;
1239 close_file(fsp,False);
1240 return NT_STATUS_OK;
1243 /*******************************************************************
1244 Check if a user is allowed to delete a file.
1245 ********************************************************************/
1247 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1249 SMB_STRUCT_STAT sbuf;
1255 if (!CAN_WRITE(conn))
1256 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1258 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1259 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1261 fmode = dos_mode(conn,fname,&sbuf);
1263 return NT_STATUS_FILE_IS_A_DIRECTORY;
1264 if (!lp_delete_readonly(SNUM(conn))) {
1266 return NT_STATUS_CANNOT_DELETE;
1268 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1269 return NT_STATUS_CANNOT_DELETE;
1271 /* We need a better way to return NT status codes from open... */
1275 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1276 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1279 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1280 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1281 ret = unix_ERR_ntstatus;
1282 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1283 ret = NT_STATUS_SHARING_VIOLATION;
1286 unix_ERR_ntstatus = NT_STATUS_OK;
1289 close_file(fsp,False);
1290 return NT_STATUS_OK;
1293 /****************************************************************************
1294 The guts of the unlink command, split out so it may be called by the NT SMB
1296 ****************************************************************************/
1298 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1304 NTSTATUS error = NT_STATUS_OK;
1306 BOOL bad_path = False;
1308 SMB_STRUCT_STAT sbuf;
1310 *directory = *mask = 0;
1312 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1314 p = strrchr_m(name,'/');
1316 pstrcpy(directory,".");
1320 pstrcpy(directory,name);
1325 * We should only check the mangled cache
1326 * here if unix_convert failed. This means
1327 * that the path in 'mask' doesn't exist
1328 * on the file system and so we need to look
1329 * for a possible mangle. This patch from
1330 * Tine Smukavec <valentin.smukavec@hermes.si>.
1333 if (!rc && mangle_is_mangled(mask))
1334 mangle_check_cache( mask );
1336 has_wild = ms_has_wild(mask);
1339 pstrcat(directory,"/");
1340 pstrcat(directory,mask);
1341 error = can_delete(directory,conn,dirtype);
1342 if (!NT_STATUS_IS_OK(error)) return error;
1344 if (vfs_unlink(conn,directory) == 0) {
1348 void *dirptr = NULL;
1351 if (check_name(directory,conn))
1352 dirptr = OpenDir(conn, directory, True);
1354 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1355 the pattern matches against the long name, otherwise the short name
1356 We don't implement this yet XXXX
1360 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1362 if (strequal(mask,"????????.???"))
1365 while ((dname = ReadDirName(dirptr))) {
1367 pstrcpy(fname,dname);
1369 if(!mask_match(fname, mask, case_sensitive)) continue;
1371 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1372 error = can_delete(fname,conn,dirtype);
1373 if (!NT_STATUS_IS_OK(error)) continue;
1374 if (vfs_unlink(conn,fname) == 0) count++;
1375 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1381 if (count == 0 && NT_STATUS_IS_OK(error)) {
1382 error = map_nt_error_from_unix(errno);
1388 /****************************************************************************
1390 ****************************************************************************/
1392 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1399 START_PROFILE(SMBunlink);
1401 dirtype = SVAL(inbuf,smb_vwv0);
1403 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1405 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1407 DEBUG(3,("reply_unlink : %s\n",name));
1409 status = unlink_internals(conn, dirtype, name);
1410 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1413 * Win2k needs a changenotify request response before it will
1414 * update after a rename..
1416 process_pending_change_notify_queue((time_t)0);
1418 outsize = set_message(outbuf,0,0,True);
1420 END_PROFILE(SMBunlink);
1424 /****************************************************************************
1426 ****************************************************************************/
1428 void fail_readraw(void)
1431 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1433 exit_server(errstr);
1436 /****************************************************************************
1437 Use sendfile in readbraw.
1438 ****************************************************************************/
1440 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1441 ssize_t mincount, char *outbuf)
1445 #if defined(WITH_SENDFILE)
1447 * We can only use sendfile on a non-chained packet and on a file
1448 * that is exclusively oplocked. reply_readbraw has already checked the length.
1451 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1452 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1455 _smb_setlen(outbuf,nread);
1456 header.data = outbuf;
1460 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1462 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1463 * return ENOSYS then pretend we just got a normal read.
1465 if (errno == ENOSYS)
1468 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1469 fsp->fsp_name, strerror(errno) ));
1470 exit_server("send_file_readbraw sendfile failed");
1479 ret = read_file(fsp,outbuf+4,startpos,nread);
1484 _smb_setlen(outbuf,ret);
1485 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1489 /****************************************************************************
1490 Reply to a readbraw (core+ protocol).
1491 ****************************************************************************/
1493 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1495 ssize_t maxcount,mincount;
1498 char *header = outbuf;
1500 START_PROFILE(SMBreadbraw);
1503 * Special check if an oplock break has been issued
1504 * and the readraw request croses on the wire, we must
1505 * return a zero length response here.
1508 if(global_oplock_break) {
1509 _smb_setlen(header,0);
1510 if (write_data(smbd_server_fd(),header,4) != 4)
1512 DEBUG(5,("readbraw - oplock break finished\n"));
1513 END_PROFILE(SMBreadbraw);
1517 fsp = file_fsp(inbuf,smb_vwv0);
1519 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1521 * fsp could be NULL here so use the value from the packet. JRA.
1523 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1524 _smb_setlen(header,0);
1525 if (write_data(smbd_server_fd(),header,4) != 4)
1527 END_PROFILE(SMBreadbraw);
1531 CHECK_FSP(fsp,conn);
1533 flush_write_cache(fsp, READRAW_FLUSH);
1535 startpos = IVAL(inbuf,smb_vwv1);
1536 if(CVAL(inbuf,smb_wct) == 10) {
1538 * This is a large offset (64 bit) read.
1540 #ifdef LARGE_SMB_OFF_T
1542 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1544 #else /* !LARGE_SMB_OFF_T */
1547 * Ensure we haven't been sent a >32 bit offset.
1550 if(IVAL(inbuf,smb_vwv8) != 0) {
1551 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1552 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1553 _smb_setlen(header,0);
1554 if (write_data(smbd_server_fd(),header,4) != 4)
1556 END_PROFILE(SMBreadbraw);
1560 #endif /* LARGE_SMB_OFF_T */
1563 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1564 _smb_setlen(header,0);
1565 if (write_data(smbd_server_fd(),header,4) != 4)
1567 END_PROFILE(SMBreadbraw);
1571 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1572 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1574 /* ensure we don't overrun the packet size */
1575 maxcount = MIN(65535,maxcount);
1576 maxcount = MAX(mincount,maxcount);
1578 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1579 SMB_OFF_T size = fsp->size;
1580 SMB_OFF_T sizeneeded = startpos + maxcount;
1582 if (size < sizeneeded) {
1584 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1586 if (!fsp->can_write)
1590 if (startpos >= size)
1593 nread = MIN(maxcount,(size - startpos));
1596 if (nread < mincount)
1599 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1600 (int)maxcount, (int)mincount, (int)nread ) );
1602 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1604 DEBUG(5,("readbraw finished\n"));
1605 END_PROFILE(SMBreadbraw);
1609 /****************************************************************************
1610 Reply to a lockread (core+ protocol).
1611 ****************************************************************************/
1613 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1621 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1622 START_PROFILE(SMBlockread);
1624 CHECK_FSP(fsp,conn);
1627 release_level_2_oplocks_on_change(fsp);
1629 numtoread = SVAL(inbuf,smb_vwv1);
1630 startpos = IVAL(inbuf,smb_vwv2);
1632 outsize = set_message(outbuf,5,3,True);
1633 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1634 data = smb_buf(outbuf) + 3;
1637 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1638 * protocol request that predates the read/write lock concept.
1639 * Thus instead of asking for a read lock here we need to ask
1640 * for a write lock. JRA.
1643 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1644 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1646 if (NT_STATUS_V(status)) {
1647 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1649 * A blocking lock was requested. Package up
1650 * this smb into a queued request and push it
1651 * onto the blocking lock queue.
1653 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
1654 END_PROFILE(SMBlockread);
1658 END_PROFILE(SMBlockread);
1659 return ERROR_NT(status);
1662 nread = read_file(fsp,data,startpos,numtoread);
1665 END_PROFILE(SMBlockread);
1666 return(UNIXERROR(ERRDOS,ERRnoaccess));
1670 SSVAL(outbuf,smb_vwv0,nread);
1671 SSVAL(outbuf,smb_vwv5,nread+3);
1672 SSVAL(smb_buf(outbuf),1,nread);
1674 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1675 fsp->fnum, (int)numtoread, (int)nread));
1677 END_PROFILE(SMBlockread);
1681 /****************************************************************************
1683 ****************************************************************************/
1685 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1692 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1693 START_PROFILE(SMBread);
1695 CHECK_FSP(fsp,conn);
1698 numtoread = SVAL(inbuf,smb_vwv1);
1699 startpos = IVAL(inbuf,smb_vwv2);
1701 outsize = set_message(outbuf,5,3,True);
1702 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1703 data = smb_buf(outbuf) + 3;
1705 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1706 END_PROFILE(SMBread);
1707 return ERROR_DOS(ERRDOS,ERRlock);
1711 nread = read_file(fsp,data,startpos,numtoread);
1714 END_PROFILE(SMBread);
1715 return(UNIXERROR(ERRDOS,ERRnoaccess));
1719 SSVAL(outbuf,smb_vwv0,nread);
1720 SSVAL(outbuf,smb_vwv5,nread+3);
1721 SCVAL(smb_buf(outbuf),0,1);
1722 SSVAL(smb_buf(outbuf),1,nread);
1724 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1725 fsp->fnum, (int)numtoread, (int)nread ) );
1727 END_PROFILE(SMBread);
1731 /****************************************************************************
1732 Reply to a read and X - possibly using sendfile.
1733 ****************************************************************************/
1735 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1736 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1739 char *data = smb_buf(outbuf);
1741 #if defined(WITH_SENDFILE)
1743 * We can only use sendfile on a non-chained packet and on a file
1744 * that is exclusively oplocked.
1747 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1748 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1749 SMB_STRUCT_STAT sbuf;
1752 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
1753 return(UNIXERROR(ERRDOS,ERRnoaccess));
1755 if (startpos > sbuf.st_size)
1758 if (smb_maxcnt > (sbuf.st_size - startpos))
1759 smb_maxcnt = (sbuf.st_size - startpos);
1761 if (smb_maxcnt == 0)
1765 * Set up the packet header before send. We
1766 * assume here the sendfile will work (get the
1767 * correct amount of data).
1770 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1771 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1772 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1773 SCVAL(outbuf,smb_vwv0,0xFF);
1774 set_message(outbuf,12,smb_maxcnt,False);
1775 header.data = outbuf;
1776 header.length = data - outbuf;
1779 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1781 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1782 * return ENOSYS then pretend we just got a normal read.
1784 if (errno == ENOSYS)
1787 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1788 fsp->fsp_name, strerror(errno) ));
1789 exit_server("send_file_readX sendfile failed");
1792 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1793 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1801 nread = read_file(fsp,data,startpos,smb_maxcnt);
1804 END_PROFILE(SMBreadX);
1805 return(UNIXERROR(ERRDOS,ERRnoaccess));
1808 SSVAL(outbuf,smb_vwv5,nread);
1809 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1810 SSVAL(smb_buf(outbuf),-2,nread);
1812 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1813 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1818 /****************************************************************************
1819 Reply to a read and X.
1820 ****************************************************************************/
1822 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1824 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1825 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1827 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1829 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1832 START_PROFILE(SMBreadX);
1834 /* If it's an IPC, pass off the pipe handler. */
1836 END_PROFILE(SMBreadX);
1837 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1840 CHECK_FSP(fsp,conn);
1843 set_message(outbuf,12,0,True);
1845 if(CVAL(inbuf,smb_wct) == 12) {
1846 #ifdef LARGE_SMB_OFF_T
1848 * This is a large offset (64 bit) read.
1850 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1852 #else /* !LARGE_SMB_OFF_T */
1855 * Ensure we haven't been sent a >32 bit offset.
1858 if(IVAL(inbuf,smb_vwv10) != 0) {
1859 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1860 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1861 END_PROFILE(SMBreadX);
1862 return ERROR_DOS(ERRDOS,ERRbadaccess);
1865 #endif /* LARGE_SMB_OFF_T */
1869 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1870 END_PROFILE(SMBreadX);
1871 return ERROR_DOS(ERRDOS,ERRlock);
1874 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1876 nread = chain_reply(inbuf,outbuf,length,bufsize);
1878 END_PROFILE(SMBreadX);
1882 /****************************************************************************
1883 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1884 ****************************************************************************/
1886 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1889 ssize_t total_written=0;
1890 size_t numtowrite=0;
1895 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1897 START_PROFILE(SMBwritebraw);
1899 CHECK_FSP(fsp,conn);
1902 tcount = IVAL(inbuf,smb_vwv1);
1903 startpos = IVAL(inbuf,smb_vwv3);
1904 write_through = BITSETW(inbuf+smb_vwv7,0);
1906 /* We have to deal with slightly different formats depending
1907 on whether we are using the core+ or lanman1.0 protocol */
1909 if(Protocol <= PROTOCOL_COREPLUS) {
1910 numtowrite = SVAL(smb_buf(inbuf),-2);
1911 data = smb_buf(inbuf);
1913 numtowrite = SVAL(inbuf,smb_vwv10);
1914 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1917 /* force the error type */
1918 SCVAL(inbuf,smb_com,SMBwritec);
1919 SCVAL(outbuf,smb_com,SMBwritec);
1921 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1922 END_PROFILE(SMBwritebraw);
1923 return(ERROR_DOS(ERRDOS,ERRlock));
1927 nwritten = write_file(fsp,data,startpos,numtowrite);
1929 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1930 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1932 if (nwritten < numtowrite) {
1933 END_PROFILE(SMBwritebraw);
1934 return(UNIXERROR(ERRHRD,ERRdiskfull));
1937 total_written = nwritten;
1939 /* Return a message to the redirector to tell it to send more bytes */
1940 SCVAL(outbuf,smb_com,SMBwritebraw);
1941 SSVALS(outbuf,smb_vwv0,-1);
1942 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1943 if (!send_smb(smbd_server_fd(),outbuf))
1944 exit_server("reply_writebraw: send_smb failed.");
1946 /* Now read the raw data into the buffer and write it */
1947 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1948 exit_server("secondary writebraw failed");
1951 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1952 numtowrite = smb_len(inbuf);
1954 /* Set up outbuf to return the correct return */
1955 outsize = set_message(outbuf,1,0,True);
1956 SCVAL(outbuf,smb_com,SMBwritec);
1957 SSVAL(outbuf,smb_vwv0,total_written);
1959 if (numtowrite != 0) {
1961 if (numtowrite > BUFFER_SIZE) {
1962 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1963 (unsigned int)numtowrite ));
1964 exit_server("secondary writebraw failed");
1967 if (tcount > nwritten+numtowrite) {
1968 DEBUG(3,("Client overestimated the write %d %d %d\n",
1969 (int)tcount,(int)nwritten,(int)numtowrite));
1972 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1973 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1975 exit_server("secondary writebraw failed");
1978 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1980 if (nwritten < (ssize_t)numtowrite) {
1981 SCVAL(outbuf,smb_rcls,ERRHRD);
1982 SSVAL(outbuf,smb_err,ERRdiskfull);
1986 total_written += nwritten;
1989 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1990 sync_file(conn,fsp);
1992 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1993 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1995 /* we won't return a status if write through is not selected - this follows what WfWg does */
1996 END_PROFILE(SMBwritebraw);
1997 if (!write_through && total_written==tcount) {
1999 #if RABBIT_PELLET_FIX
2001 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2002 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2004 if (!send_keepalive(smbd_server_fd()))
2005 exit_server("reply_writebraw: send of keepalive failed");
2013 /****************************************************************************
2014 Reply to a writeunlock (core+).
2015 ****************************************************************************/
2017 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2018 int size, int dum_buffsize)
2020 ssize_t nwritten = -1;
2025 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2027 START_PROFILE(SMBwriteunlock);
2029 CHECK_FSP(fsp,conn);
2032 numtowrite = SVAL(inbuf,smb_vwv1);
2033 startpos = IVAL(inbuf,smb_vwv2);
2034 data = smb_buf(inbuf) + 3;
2036 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2037 WRITE_LOCK,False)) {
2038 END_PROFILE(SMBwriteunlock);
2039 return ERROR_DOS(ERRDOS,ERRlock);
2042 /* The special X/Open SMB protocol handling of
2043 zero length writes is *NOT* done for
2048 nwritten = write_file(fsp,data,startpos,numtowrite);
2050 if (lp_syncalways(SNUM(conn)))
2051 sync_file(conn,fsp);
2053 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2054 END_PROFILE(SMBwriteunlock);
2055 return(UNIXERROR(ERRDOS,ERRnoaccess));
2058 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2059 (SMB_BIG_UINT)startpos);
2060 if (NT_STATUS_V(status)) {
2061 END_PROFILE(SMBwriteunlock);
2062 return ERROR_NT(status);
2065 outsize = set_message(outbuf,1,0,True);
2067 SSVAL(outbuf,smb_vwv0,nwritten);
2069 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2070 fsp->fnum, (int)numtowrite, (int)nwritten));
2072 END_PROFILE(SMBwriteunlock);
2076 /****************************************************************************
2078 ****************************************************************************/
2080 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2083 ssize_t nwritten = -1;
2086 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2088 START_PROFILE(SMBwrite);
2090 /* If it's an IPC, pass off the pipe handler. */
2092 END_PROFILE(SMBwrite);
2093 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2096 CHECK_FSP(fsp,conn);
2099 numtowrite = SVAL(inbuf,smb_vwv1);
2100 startpos = IVAL(inbuf,smb_vwv2);
2101 data = smb_buf(inbuf) + 3;
2103 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2104 END_PROFILE(SMBwrite);
2105 return ERROR_DOS(ERRDOS,ERRlock);
2109 * X/Open SMB protocol says that if smb_vwv1 is
2110 * zero then the file size should be extended or
2111 * truncated to the size given in smb_vwv[2-3].
2114 if(numtowrite == 0) {
2116 * This is actually an allocate call, and set EOF. JRA.
2118 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2120 END_PROFILE(SMBwrite);
2121 return ERROR_NT(NT_STATUS_DISK_FULL);
2123 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2125 END_PROFILE(SMBwrite);
2126 return ERROR_NT(NT_STATUS_DISK_FULL);
2129 nwritten = write_file(fsp,data,startpos,numtowrite);
2131 if (lp_syncalways(SNUM(conn)))
2132 sync_file(conn,fsp);
2134 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2135 END_PROFILE(SMBwrite);
2136 return(UNIXERROR(ERRDOS,ERRnoaccess));
2139 outsize = set_message(outbuf,1,0,True);
2141 SSVAL(outbuf,smb_vwv0,nwritten);
2143 if (nwritten < (ssize_t)numtowrite) {
2144 SCVAL(outbuf,smb_rcls,ERRHRD);
2145 SSVAL(outbuf,smb_err,ERRdiskfull);
2148 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2150 END_PROFILE(SMBwrite);
2154 /****************************************************************************
2155 Reply to a write and X.
2156 ****************************************************************************/
2158 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2160 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2161 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2162 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2163 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2164 ssize_t nwritten = -1;
2165 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2166 unsigned int smblen = smb_len(inbuf);
2168 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2169 START_PROFILE(SMBwriteX);
2171 /* If it's an IPC, pass off the pipe handler. */
2173 END_PROFILE(SMBwriteX);
2174 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2177 CHECK_FSP(fsp,conn);
2180 /* Deal with possible LARGE_WRITEX */
2182 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2184 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2185 END_PROFILE(SMBwriteX);
2186 return ERROR_DOS(ERRDOS,ERRbadmem);
2189 data = smb_base(inbuf) + smb_doff;
2191 if(CVAL(inbuf,smb_wct) == 14) {
2192 #ifdef LARGE_SMB_OFF_T
2194 * This is a large offset (64 bit) write.
2196 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2198 #else /* !LARGE_SMB_OFF_T */
2201 * Ensure we haven't been sent a >32 bit offset.
2204 if(IVAL(inbuf,smb_vwv12) != 0) {
2205 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2206 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2207 END_PROFILE(SMBwriteX);
2208 return ERROR_DOS(ERRDOS,ERRbadaccess);
2211 #endif /* LARGE_SMB_OFF_T */
2214 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2215 END_PROFILE(SMBwriteX);
2216 return ERROR_DOS(ERRDOS,ERRlock);
2219 /* X/Open SMB protocol says that, unlike SMBwrite
2220 if the length is zero then NO truncation is
2221 done, just a write of zero. To truncate a file,
2226 nwritten = write_file(fsp,data,startpos,numtowrite);
2228 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2229 END_PROFILE(SMBwriteX);
2230 return(UNIXERROR(ERRDOS,ERRnoaccess));
2233 set_message(outbuf,6,0,True);
2235 SSVAL(outbuf,smb_vwv2,nwritten);
2237 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2239 if (nwritten < (ssize_t)numtowrite) {
2240 SCVAL(outbuf,smb_rcls,ERRHRD);
2241 SSVAL(outbuf,smb_err,ERRdiskfull);
2244 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2245 fsp->fnum, (int)numtowrite, (int)nwritten));
2247 if (lp_syncalways(SNUM(conn)) || write_through)
2248 sync_file(conn,fsp);
2250 END_PROFILE(SMBwriteX);
2251 return chain_reply(inbuf,outbuf,length,bufsize);
2254 /****************************************************************************
2256 ****************************************************************************/
2258 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2264 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2265 START_PROFILE(SMBlseek);
2267 CHECK_FSP(fsp,conn);
2269 flush_write_cache(fsp, SEEK_FLUSH);
2271 mode = SVAL(inbuf,smb_vwv1) & 3;
2272 startpos = IVALS(inbuf,smb_vwv2);
2275 case 0: umode = SEEK_SET; break;
2276 case 1: umode = SEEK_CUR; break;
2277 case 2: umode = SEEK_END; break;
2279 umode = SEEK_SET; break;
2282 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2284 * Check for the special case where a seek before the start
2285 * of the file sets the offset to zero. Added in the CIFS spec,
2289 if(errno == EINVAL) {
2290 SMB_OFF_T current_pos = startpos;
2292 if(umode == SEEK_CUR) {
2294 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2295 END_PROFILE(SMBlseek);
2296 return(UNIXERROR(ERRDOS,ERRnoaccess));
2299 current_pos += startpos;
2301 } else if (umode == SEEK_END) {
2303 SMB_STRUCT_STAT sbuf;
2305 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2306 END_PROFILE(SMBlseek);
2307 return(UNIXERROR(ERRDOS,ERRnoaccess));
2310 current_pos += sbuf.st_size;
2314 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2318 END_PROFILE(SMBlseek);
2319 return(UNIXERROR(ERRDOS,ERRnoaccess));
2325 outsize = set_message(outbuf,2,0,True);
2326 SIVAL(outbuf,smb_vwv0,res);
2328 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2329 fsp->fnum, (double)startpos, (double)res, mode));
2331 END_PROFILE(SMBlseek);
2335 /****************************************************************************
2337 ****************************************************************************/
2339 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2341 int outsize = set_message(outbuf,0,0,True);
2342 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2343 START_PROFILE(SMBflush);
2345 CHECK_FSP(fsp,conn);
2348 file_sync_all(conn);
2350 sync_file(conn,fsp);
2353 DEBUG(3,("flush\n"));
2354 END_PROFILE(SMBflush);
2358 /****************************************************************************
2360 ****************************************************************************/
2362 int reply_exit(connection_struct *conn,
2363 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2366 START_PROFILE(SMBexit);
2367 outsize = set_message(outbuf,0,0,True);
2369 DEBUG(3,("exit\n"));
2371 END_PROFILE(SMBexit);
2375 /****************************************************************************
2376 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2377 ****************************************************************************/
2379 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2384 int32 eclass = 0, err = 0;
2385 files_struct *fsp = NULL;
2386 START_PROFILE(SMBclose);
2388 outsize = set_message(outbuf,0,0,True);
2390 /* If it's an IPC, pass off to the pipe handler. */
2392 END_PROFILE(SMBclose);
2393 return reply_pipe_close(conn, inbuf,outbuf);
2396 fsp = file_fsp(inbuf,smb_vwv0);
2399 * We can only use CHECK_FSP if we know it's not a directory.
2402 if(!fsp || (fsp->conn != conn)) {
2403 END_PROFILE(SMBclose);
2404 return ERROR_DOS(ERRDOS,ERRbadfid);
2407 if(fsp->is_directory) {
2409 * Special case - close NT SMB directory handle.
2411 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2412 close_file(fsp,True);
2415 * Close ordinary file.
2420 /* Save the name for time set in close. */
2421 pstrcpy( file_name, fsp->fsp_name);
2423 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2425 conn->num_files_open));
2428 * close_file() returns the unix errno if an error
2429 * was detected on close - normally this is due to
2430 * a disk full error. If not then it was probably an I/O error.
2433 if((close_err = close_file(fsp,True)) != 0) {
2435 END_PROFILE(SMBclose);
2436 return (UNIXERROR(ERRHRD,ERRgeneral));
2440 * Now take care of any time sent in the close.
2443 mtime = make_unix_date3(inbuf+smb_vwv1);
2445 /* try and set the date */
2446 set_filetime(conn, file_name, mtime);
2450 /* We have a cached error */
2452 END_PROFILE(SMBclose);
2453 return ERROR_DOS(eclass,err);
2456 END_PROFILE(SMBclose);
2460 /****************************************************************************
2461 Reply to a writeclose (Core+ protocol).
2462 ****************************************************************************/
2464 int reply_writeclose(connection_struct *conn,
2465 char *inbuf,char *outbuf, int size, int dum_buffsize)
2468 ssize_t nwritten = -1;
2474 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2475 START_PROFILE(SMBwriteclose);
2477 CHECK_FSP(fsp,conn);
2480 numtowrite = SVAL(inbuf,smb_vwv1);
2481 startpos = IVAL(inbuf,smb_vwv2);
2482 mtime = make_unix_date3(inbuf+smb_vwv4);
2483 data = smb_buf(inbuf) + 1;
2485 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2486 END_PROFILE(SMBwriteclose);
2487 return ERROR_DOS(ERRDOS,ERRlock);
2490 nwritten = write_file(fsp,data,startpos,numtowrite);
2492 set_filetime(conn, fsp->fsp_name,mtime);
2494 close_err = close_file(fsp,True);
2496 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2497 fsp->fnum, (int)numtowrite, (int)nwritten,
2498 conn->num_files_open));
2500 if (nwritten <= 0) {
2501 END_PROFILE(SMBwriteclose);
2502 return(UNIXERROR(ERRDOS,ERRnoaccess));
2505 if(close_err != 0) {
2507 END_PROFILE(SMBwriteclose);
2508 return(UNIXERROR(ERRHRD,ERRgeneral));
2511 outsize = set_message(outbuf,1,0,True);
2513 SSVAL(outbuf,smb_vwv0,nwritten);
2514 END_PROFILE(SMBwriteclose);
2518 /****************************************************************************
2520 ****************************************************************************/
2522 int reply_lock(connection_struct *conn,
2523 char *inbuf,char *outbuf, int length, int dum_buffsize)
2525 int outsize = set_message(outbuf,0,0,True);
2526 SMB_BIG_UINT count,offset;
2528 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2529 START_PROFILE(SMBlock);
2531 CHECK_FSP(fsp,conn);
2533 release_level_2_oplocks_on_change(fsp);
2535 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2536 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2538 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2539 fsp->fd, fsp->fnum, (double)offset, (double)count));
2541 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2542 if (NT_STATUS_V(status)) {
2543 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2545 * A blocking lock was requested. Package up
2546 * this smb into a queued request and push it
2547 * onto the blocking lock queue.
2549 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2550 END_PROFILE(SMBlock);
2554 END_PROFILE(SMBlock);
2555 return ERROR_NT(status);
2558 END_PROFILE(SMBlock);
2562 /****************************************************************************
2564 ****************************************************************************/
2566 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2569 int outsize = set_message(outbuf,0,0,True);
2570 SMB_BIG_UINT count,offset;
2572 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2573 START_PROFILE(SMBunlock);
2575 CHECK_FSP(fsp,conn);
2577 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2578 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2580 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2581 if (NT_STATUS_V(status)) {
2582 END_PROFILE(SMBunlock);
2583 return ERROR_NT(status);
2586 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2587 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2589 END_PROFILE(SMBunlock);
2593 /****************************************************************************
2595 ****************************************************************************/
2597 int reply_tdis(connection_struct *conn,
2598 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2600 int outsize = set_message(outbuf,0,0,True);
2602 START_PROFILE(SMBtdis);
2604 vuid = SVAL(inbuf,smb_uid);
2607 DEBUG(4,("Invalid connection in tdis\n"));
2608 END_PROFILE(SMBtdis);
2609 return ERROR_DOS(ERRSRV,ERRinvnid);
2614 close_cnum(conn,vuid);
2616 END_PROFILE(SMBtdis);
2620 /****************************************************************************
2622 ****************************************************************************/
2624 int reply_echo(connection_struct *conn,
2625 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2627 int smb_reverb = SVAL(inbuf,smb_vwv0);
2629 unsigned int data_len = smb_buflen(inbuf);
2630 int outsize = set_message(outbuf,1,data_len,True);
2631 START_PROFILE(SMBecho);
2633 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2635 /* copy any incoming data back out */
2637 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2639 if (smb_reverb > 100) {
2640 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2644 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2645 SSVAL(outbuf,smb_vwv0,seq_num);
2647 smb_setlen(outbuf,outsize - 4);
2649 if (!send_smb(smbd_server_fd(),outbuf))
2650 exit_server("reply_echo: send_smb failed.");
2653 DEBUG(3,("echo %d times\n", smb_reverb));
2657 END_PROFILE(SMBecho);
2661 /****************************************************************************
2662 Reply to a printopen.
2663 ****************************************************************************/
2665 int reply_printopen(connection_struct *conn,
2666 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2670 START_PROFILE(SMBsplopen);
2672 if (!CAN_PRINT(conn)) {
2673 END_PROFILE(SMBsplopen);
2674 return ERROR_DOS(ERRDOS,ERRnoaccess);
2677 /* Open for exclusive use, write only. */
2678 fsp = print_fsp_open(conn, NULL);
2681 END_PROFILE(SMBsplopen);
2682 return(UNIXERROR(ERRDOS,ERRnoaccess));
2685 outsize = set_message(outbuf,1,0,True);
2686 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2688 DEBUG(3,("openprint fd=%d fnum=%d\n",
2689 fsp->fd, fsp->fnum));
2691 END_PROFILE(SMBsplopen);
2695 /****************************************************************************
2696 Reply to a printclose.
2697 ****************************************************************************/
2698 int reply_printclose(connection_struct *conn,
2699 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2701 int outsize = set_message(outbuf,0,0,True);
2702 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2704 START_PROFILE(SMBsplclose);
2706 CHECK_FSP(fsp,conn);
2708 if (!CAN_PRINT(conn)) {
2709 END_PROFILE(SMBsplclose);
2710 return ERROR_DOS(ERRDOS,ERRnoaccess);
2713 DEBUG(3,("printclose fd=%d fnum=%d\n",
2714 fsp->fd,fsp->fnum));
2716 close_err = close_file(fsp,True);
2718 if(close_err != 0) {
2720 END_PROFILE(SMBsplclose);
2721 return(UNIXERROR(ERRHRD,ERRgeneral));
2724 END_PROFILE(SMBsplclose);
2728 /****************************************************************************
2729 Reply to a printqueue.
2730 ****************************************************************************/
2732 int reply_printqueue(connection_struct *conn,
2733 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2735 int outsize = set_message(outbuf,2,3,True);
2736 int max_count = SVAL(inbuf,smb_vwv0);
2737 int start_index = SVAL(inbuf,smb_vwv1);
2738 START_PROFILE(SMBsplretq);
2740 /* we used to allow the client to get the cnum wrong, but that
2741 is really quite gross and only worked when there was only
2742 one printer - I think we should now only accept it if they
2743 get it right (tridge) */
2744 if (!CAN_PRINT(conn)) {
2745 END_PROFILE(SMBsplretq);
2746 return ERROR_DOS(ERRDOS,ERRnoaccess);
2749 SSVAL(outbuf,smb_vwv0,0);
2750 SSVAL(outbuf,smb_vwv1,0);
2751 SCVAL(smb_buf(outbuf),0,1);
2752 SSVAL(smb_buf(outbuf),1,0);
2754 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2755 start_index, max_count));
2758 print_queue_struct *queue = NULL;
2759 print_status_struct status;
2760 char *p = smb_buf(outbuf) + 3;
2761 int count = print_queue_status(SNUM(conn), &queue, &status);
2762 int num_to_get = ABS(max_count);
2763 int first = (max_count>0?start_index:start_index+max_count+1);
2769 num_to_get = MIN(num_to_get,count-first);
2772 for (i=first;i<first+num_to_get;i++) {
2773 put_dos_date2(p,0,queue[i].time);
2774 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2775 SSVAL(p,5, queue[i].job);
2776 SIVAL(p,7,queue[i].size);
2778 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2783 outsize = set_message(outbuf,2,28*count+3,False);
2784 SSVAL(outbuf,smb_vwv0,count);
2785 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2786 SCVAL(smb_buf(outbuf),0,1);
2787 SSVAL(smb_buf(outbuf),1,28*count);
2792 DEBUG(3,("%d entries returned in queue\n",count));
2795 END_PROFILE(SMBsplretq);
2799 /****************************************************************************
2800 Reply to a printwrite.
2801 ****************************************************************************/
2803 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2806 int outsize = set_message(outbuf,0,0,True);
2808 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2809 START_PROFILE(SMBsplwr);
2811 if (!CAN_PRINT(conn)) {
2812 END_PROFILE(SMBsplwr);
2813 return ERROR_DOS(ERRDOS,ERRnoaccess);
2816 CHECK_FSP(fsp,conn);
2819 numtowrite = SVAL(smb_buf(inbuf),1);
2820 data = smb_buf(inbuf) + 3;
2822 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2823 END_PROFILE(SMBsplwr);
2824 return(UNIXERROR(ERRDOS,ERRnoaccess));
2827 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2829 END_PROFILE(SMBsplwr);
2833 /****************************************************************************
2834 The guts of the mkdir command, split out so it may be called by the NT SMB
2836 ****************************************************************************/
2838 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2840 BOOL bad_path = False;
2841 SMB_STRUCT_STAT sbuf;
2844 unix_convert(directory,conn,0,&bad_path,&sbuf);
2846 if (check_name(directory, conn))
2847 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2850 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2851 if (!NT_STATUS_IS_OK(nterr))
2853 return map_nt_error_from_unix(errno);
2856 return NT_STATUS_OK;
2859 /****************************************************************************
2861 ****************************************************************************/
2863 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2868 START_PROFILE(SMBmkdir);
2870 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2872 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2874 status = mkdir_internal(conn, directory);
2875 if (!NT_STATUS_IS_OK(status))
2876 return ERROR_NT(status);
2878 outsize = set_message(outbuf,0,0,True);
2880 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2882 END_PROFILE(SMBmkdir);
2886 /****************************************************************************
2887 Static function used by reply_rmdir to delete an entire directory
2888 tree recursively. Return False on ok, True on fail.
2889 ****************************************************************************/
2891 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2895 void *dirptr = OpenDir(conn, directory, False);
2900 while((dname = ReadDirName(dirptr))) {
2904 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2907 /* Construct the full name. */
2908 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2914 pstrcpy(fullname, directory);
2915 pstrcat(fullname, "/");
2916 pstrcat(fullname, dname);
2918 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2923 if(st.st_mode & S_IFDIR) {
2924 if(recursive_rmdir(conn, fullname)!=0) {
2928 if(vfs_rmdir(conn,fullname) != 0) {
2932 } else if(vfs_unlink(conn,fullname) != 0) {
2941 /****************************************************************************
2942 The internals of the rmdir code - called elsewhere.
2943 ****************************************************************************/
2945 BOOL rmdir_internals(connection_struct *conn, char *directory)
2949 ok = (vfs_rmdir(conn,directory) == 0);
2950 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2952 * Check to see if the only thing in this directory are
2953 * vetoed files/directories. If so then delete them and
2954 * retry. If we fail to delete any of them (and we *don't*
2955 * do a recursive delete) then fail the rmdir.
2957 BOOL all_veto_files = True;
2959 void *dirptr = OpenDir(conn, directory, False);
2961 if(dirptr != NULL) {
2962 int dirpos = TellDir(dirptr);
2963 while ((dname = ReadDirName(dirptr))) {
2964 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2966 if(!IS_VETO_PATH(conn, dname)) {
2967 all_veto_files = False;
2972 if(all_veto_files) {
2973 SeekDir(dirptr,dirpos);
2974 while ((dname = ReadDirName(dirptr))) {
2978 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2981 /* Construct the full name. */
2982 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2987 pstrcpy(fullname, directory);
2988 pstrcat(fullname, "/");
2989 pstrcat(fullname, dname);
2991 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2993 if(st.st_mode & S_IFDIR) {
2994 if(lp_recursive_veto_delete(SNUM(conn))) {
2995 if(recursive_rmdir(conn, fullname) != 0)
2998 if(vfs_rmdir(conn,fullname) != 0)
3000 } else if(vfs_unlink(conn,fullname) != 0)
3004 /* Retry the rmdir */
3005 ok = (vfs_rmdir(conn,directory) == 0);
3015 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3020 /****************************************************************************
3022 ****************************************************************************/
3024 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3029 BOOL bad_path = False;
3030 SMB_STRUCT_STAT sbuf;
3031 START_PROFILE(SMBrmdir);
3033 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3035 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3037 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3039 if (check_name(directory,conn))
3041 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3042 ok = rmdir_internals(conn, directory);
3047 set_bad_path_error(errno, bad_path);
3048 END_PROFILE(SMBrmdir);
3049 return(UNIXERROR(ERRDOS,ERRbadpath));
3052 outsize = set_message(outbuf,0,0,True);
3054 DEBUG( 3, ( "rmdir %s\n", directory ) );
3056 END_PROFILE(SMBrmdir);
3060 /*******************************************************************
3061 Resolve wildcards in a filename rename.
3062 ********************************************************************/
3064 static BOOL resolve_wildcards(char *name1,char *name2)
3066 fstring root1,root2;
3070 name1 = strrchr_m(name1,'/');
3071 name2 = strrchr_m(name2,'/');
3073 if (!name1 || !name2) return(False);
3075 fstrcpy(root1,name1);
3076 fstrcpy(root2,name2);
3077 p = strrchr_m(root1,'.');
3084 p = strrchr_m(root2,'.');
3116 pstrcpy(name2,root2);
3119 pstrcat(name2,ext2);
3125 /****************************************************************************
3126 The guts of the rename command, split out so it may be called by the NT SMB
3128 ****************************************************************************/
3130 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3134 pstring newname_last_component;
3137 BOOL bad_path1 = False;
3138 BOOL bad_path2 = False;
3140 NTSTATUS error = NT_STATUS_OK;
3142 SMB_STRUCT_STAT sbuf1, sbuf2;
3144 *directory = *mask = 0;
3146 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3147 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3150 * Split the old name into directory and last component
3151 * strings. Note that unix_convert may have stripped off a
3152 * leading ./ from both name and newname if the rename is
3153 * at the root of the share. We need to make sure either both
3154 * name and newname contain a / character or neither of them do
3155 * as this is checked in resolve_wildcards().
3158 p = strrchr_m(name,'/');
3160 pstrcpy(directory,".");
3164 pstrcpy(directory,name);
3166 *p = '/'; /* Replace needed for exceptional test below. */
3170 * We should only check the mangled cache
3171 * here if unix_convert failed. This means
3172 * that the path in 'mask' doesn't exist
3173 * on the file system and so we need to look
3174 * for a possible mangle. This patch from
3175 * Tine Smukavec <valentin.smukavec@hermes.si>.
3178 if (!rc && mangle_is_mangled(mask))
3179 mangle_check_cache( mask );
3181 has_wild = ms_has_wild(mask);
3185 * No wildcards - just process the one file.
3187 BOOL is_short_name = mangle_is_8_3(name, True);
3189 /* Add a terminating '/' to the directory name. */
3190 pstrcat(directory,"/");
3191 pstrcat(directory,mask);
3193 /* Ensure newname contains a '/' also */
3194 if(strrchr_m(newname,'/') == 0) {
3197 pstrcpy(tmpstr, "./");
3198 pstrcat(tmpstr, newname);
3199 pstrcpy(newname, tmpstr);
3202 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3203 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3204 case_sensitive, case_preserve, short_case_preserve, directory,
3205 newname, newname_last_component, is_short_name));
3208 * Check for special case with case preserving and not
3209 * case sensitive, if directory and newname are identical,
3210 * and the old last component differs from the original
3211 * last component only by case, then we should allow
3212 * the rename (user is trying to change the case of the
3215 if((case_sensitive == False) &&
3216 (((case_preserve == True) &&
3217 (is_short_name == False)) ||
3218 ((short_case_preserve == True) &&
3219 (is_short_name == True))) &&
3220 strcsequal(directory, newname)) {
3221 pstring newname_modified_last_component;
3224 * Get the last component of the modified name.
3225 * Note that we guarantee that newname contains a '/'
3228 p = strrchr_m(newname,'/');
3229 pstrcpy(newname_modified_last_component,p+1);
3231 if(strcsequal(newname_modified_last_component,
3232 newname_last_component) == False) {
3234 * Replace the modified last component with
3237 pstrcpy(p+1, newname_last_component);
3241 resolve_wildcards(directory,newname);
3244 * The source object must exist.
3247 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3248 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3249 directory,newname));
3251 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3253 * Must return different errors depending on whether the parent
3254 * directory existed or not.
3257 p = strrchr_m(directory, '/');
3259 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3261 if (vfs_object_exist(conn, directory, NULL))
3262 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3263 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3265 error = map_nt_error_from_unix(errno);
3266 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3267 nt_errstr(error), directory,newname));
3272 error = can_rename(directory,conn,&sbuf1);
3274 if (!NT_STATUS_IS_OK(error)) {
3275 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3276 nt_errstr(error), directory,newname));
3281 * If the src and dest names are identical - including case,
3282 * don't do the rename, just return success.
3285 if (strcsequal(directory, newname)) {
3286 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3287 return NT_STATUS_OK;
3290 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3291 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3292 directory,newname));
3293 return NT_STATUS_OBJECT_NAME_COLLISION;
3296 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3297 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3298 directory,newname));
3299 return NT_STATUS_OK;
3302 if (errno == ENOTDIR || errno == EISDIR)
3303 error = NT_STATUS_OBJECT_NAME_COLLISION;
3305 error = map_nt_error_from_unix(errno);
3307 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3308 nt_errstr(error), directory,newname));
3313 * Wildcards - process each file that matches.
3315 void *dirptr = NULL;
3319 if (check_name(directory,conn))
3320 dirptr = OpenDir(conn, directory, True);
3323 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3325 if (strequal(mask,"????????.???"))
3328 while ((dname = ReadDirName(dirptr))) {
3331 pstrcpy(fname,dname);
3333 if(!mask_match(fname, mask, case_sensitive))
3336 error = NT_STATUS_ACCESS_DENIED;
3337 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3338 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3339 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3340 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3343 error = can_rename(fname,conn,&sbuf1);
3344 if (!NT_STATUS_IS_OK(error)) {
3345 DEBUG(6,("rename %s refused\n", fname));
3348 pstrcpy(destname,newname);
3350 if (!resolve_wildcards(fname,destname)) {
3351 DEBUG(6,("resolve_wildcards %s %s failed\n",
3356 if (!replace_if_exists &&
3357 vfs_file_exist(conn,destname, NULL)) {
3358 DEBUG(6,("file_exist %s\n", destname));
3359 error = NT_STATUS_OBJECT_NAME_COLLISION;
3363 if (!conn->vfs_ops.rename(conn,fname,destname))
3365 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3371 if (count == 0 && NT_STATUS_IS_OK(error)) {
3372 error = map_nt_error_from_unix(errno);
3378 /****************************************************************************
3380 ****************************************************************************/
3382 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3391 START_PROFILE(SMBmv);
3393 p = smb_buf(inbuf) + 1;
3394 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3396 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3398 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3399 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3401 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3403 status = rename_internals(conn, name, newname, False);
3404 if (!NT_STATUS_IS_OK(status)) {
3405 return ERROR_NT(status);
3409 * Win2k needs a changenotify request response before it will
3410 * update after a rename..
3412 process_pending_change_notify_queue((time_t)0);
3413 outsize = set_message(outbuf,0,0,True);
3419 /*******************************************************************
3420 Copy a file as part of a reply_copy.
3421 ******************************************************************/
3423 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3424 int count,BOOL target_is_directory, int *err_ret)
3427 SMB_STRUCT_STAT src_sbuf, sbuf2;
3429 files_struct *fsp1,*fsp2;
3434 pstrcpy(dest,dest1);
3435 if (target_is_directory) {
3436 char *p = strrchr_m(src,'/');
3445 if (!vfs_file_exist(conn,src,&src_sbuf))
3448 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3449 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3454 if (!target_is_directory && count)
3455 ofun = FILE_EXISTS_OPEN;
3457 if (vfs_stat(conn,dest,&sbuf2) == -1)
3458 ZERO_STRUCTP(&sbuf2);
3460 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3461 ofun,src_sbuf.st_mode,0,&Access,&action);
3464 close_file(fsp1,False);
3468 if ((ofun&3) == 1) {
3469 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3470 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3472 * Stop the copy from occurring.
3475 src_sbuf.st_size = 0;
3479 if (src_sbuf.st_size)
3480 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3482 close_file(fsp1,False);
3484 /* Ensure the modtime is set correctly on the destination file. */
3485 fsp2->pending_modtime = src_sbuf.st_mtime;
3488 * As we are opening fsp1 read-only we only expect
3489 * an error on close on fsp2 if we are out of space.
3490 * Thus we don't look at the error return from the
3493 *err_ret = close_file(fsp2,False);
3495 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3498 /****************************************************************************
3499 Reply to a file copy.
3500 ****************************************************************************/
3502 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3507 pstring mask,newname;
3510 int error = ERRnoaccess;
3514 int tid2 = SVAL(inbuf,smb_vwv0);
3515 int ofun = SVAL(inbuf,smb_vwv1);
3516 int flags = SVAL(inbuf,smb_vwv2);
3517 BOOL target_is_directory=False;
3518 BOOL bad_path1 = False;
3519 BOOL bad_path2 = False;
3521 SMB_STRUCT_STAT sbuf1, sbuf2;
3522 START_PROFILE(SMBcopy);
3524 *directory = *mask = 0;
3527 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3528 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3530 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3532 if (tid2 != conn->cnum) {
3533 /* can't currently handle inter share copies XXXX */
3534 DEBUG(3,("Rejecting inter-share copy\n"));
3535 END_PROFILE(SMBcopy);
3536 return ERROR_DOS(ERRSRV,ERRinvdevice);
3539 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3540 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3542 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3543 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3545 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3547 if ((flags&1) && target_is_directory) {
3548 END_PROFILE(SMBcopy);
3549 return ERROR_DOS(ERRDOS,ERRbadfile);
3552 if ((flags&2) && !target_is_directory) {
3553 END_PROFILE(SMBcopy);
3554 return ERROR_DOS(ERRDOS,ERRbadpath);
3557 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3558 /* wants a tree copy! XXXX */
3559 DEBUG(3,("Rejecting tree copy\n"));
3560 END_PROFILE(SMBcopy);
3561 return ERROR_DOS(ERRSRV,ERRerror);
3564 p = strrchr_m(name,'/');
3566 pstrcpy(directory,"./");
3570 pstrcpy(directory,name);
3575 * We should only check the mangled cache
3576 * here if unix_convert failed. This means
3577 * that the path in 'mask' doesn't exist
3578 * on the file system and so we need to look
3579 * for a possible mangle. This patch from
3580 * Tine Smukavec <valentin.smukavec@hermes.si>.
3583 if (!rc && mangle_is_mangled(mask))
3584 mangle_check_cache( mask );
3586 has_wild = ms_has_wild(mask);
3589 pstrcat(directory,"/");
3590 pstrcat(directory,mask);
3591 if (resolve_wildcards(directory,newname) &&
3592 copy_file(directory,newname,conn,ofun,
3593 count,target_is_directory,&err)) count++;
3596 END_PROFILE(SMBcopy);
3597 return(UNIXERROR(ERRHRD,ERRgeneral));
3599 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3601 void *dirptr = NULL;
3605 if (check_name(directory,conn))
3606 dirptr = OpenDir(conn, directory, True);
3611 if (strequal(mask,"????????.???"))
3614 while ((dname = ReadDirName(dirptr))) {
3616 pstrcpy(fname,dname);
3618 if(!mask_match(fname, mask, case_sensitive))
3621 error = ERRnoaccess;
3622 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3623 pstrcpy(destname,newname);
3624 if (resolve_wildcards(fname,destname) &&
3625 copy_file(fname,destname,conn,ofun,
3626 count,target_is_directory,&err)) count++;
3627 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3635 /* Error on close... */
3637 END_PROFILE(SMBcopy);
3638 return(UNIXERROR(ERRHRD,ERRgeneral));
3642 END_PROFILE(SMBcopy);
3643 return ERROR_DOS(ERRDOS,error);
3646 if((errno == ENOENT) && (bad_path1 || bad_path2))
3648 unix_ERR_class = ERRDOS;
3649 unix_ERR_code = ERRbadpath;
3651 END_PROFILE(SMBcopy);
3652 return(UNIXERROR(ERRDOS,error));
3656 outsize = set_message(outbuf,1,0,True);
3657 SSVAL(outbuf,smb_vwv0,count);
3659 END_PROFILE(SMBcopy);
3663 /****************************************************************************
3665 ****************************************************************************/
3667 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3673 START_PROFILE(pathworks_setdir);
3676 if (!CAN_SETDIR(snum)) {
3677 END_PROFILE(pathworks_setdir);
3678 return ERROR_DOS(ERRDOS,ERRnoaccess);
3681 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3683 if (strlen(newdir) == 0) {
3686 ok = vfs_directory_exist(conn,newdir,NULL);
3688 string_set(&conn->connectpath,newdir);
3693 END_PROFILE(pathworks_setdir);
3694 return ERROR_DOS(ERRDOS,ERRbadpath);
3697 outsize = set_message(outbuf,0,0,True);
3698 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3700 DEBUG(3,("setdir %s\n", newdir));
3702 END_PROFILE(pathworks_setdir);
3706 /****************************************************************************
3707 Get a lock pid, dealing with large count requests.
3708 ****************************************************************************/
3710 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3712 if(!large_file_format)
3713 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3715 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3718 /****************************************************************************
3719 Get a lock count, dealing with large count requests.
3720 ****************************************************************************/
3722 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3724 SMB_BIG_UINT count = 0;
3726 if(!large_file_format) {
3727 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3730 #if defined(HAVE_LONGLONG)
3731 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3732 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3733 #else /* HAVE_LONGLONG */
3736 * NT4.x seems to be broken in that it sends large file (64 bit)
3737 * lockingX calls even if the CAP_LARGE_FILES was *not*
3738 * negotiated. For boxes without large unsigned ints truncate the
3739 * lock count by dropping the top 32 bits.
3742 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3743 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3744 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3745 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3746 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3749 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3750 #endif /* HAVE_LONGLONG */
3756 #if !defined(HAVE_LONGLONG)
3757 /****************************************************************************
3758 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3759 ****************************************************************************/
3761 static uint32 map_lock_offset(uint32 high, uint32 low)
3765 uint32 highcopy = high;
3768 * Try and find out how many significant bits there are in high.
3771 for(i = 0; highcopy; i++)
3775 * We use 31 bits not 32 here as POSIX
3776 * lock offsets may not be negative.
3779 mask = (~0) << (31 - i);
3782 return 0; /* Fail. */
3788 #endif /* !defined(HAVE_LONGLONG) */
3790 /****************************************************************************
3791 Get a lock offset, dealing with large offset requests.
3792 ****************************************************************************/
3794 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3796 SMB_BIG_UINT offset = 0;
3800 if(!large_file_format) {
3801 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3804 #if defined(HAVE_LONGLONG)
3805 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3806 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3807 #else /* HAVE_LONGLONG */
3810 * NT4.x seems to be broken in that it sends large file (64 bit)
3811 * lockingX calls even if the CAP_LARGE_FILES was *not*
3812 * negotiated. For boxes without large unsigned ints mangle the
3813 * lock offset by mapping the top 32 bits onto the lower 32.
3816 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3817 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3818 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3821 if((new_low = map_lock_offset(high, low)) == 0) {
3823 return (SMB_BIG_UINT)-1;
3826 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3827 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3828 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3829 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3832 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3833 #endif /* HAVE_LONGLONG */
3839 /****************************************************************************
3840 Reply to a lockingX request.
3841 ****************************************************************************/
3843 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3845 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3846 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3847 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3848 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3849 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3850 SMB_BIG_UINT count = 0, offset = 0;
3852 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3855 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3859 START_PROFILE(SMBlockingX);
3861 CHECK_FSP(fsp,conn);
3863 data = smb_buf(inbuf);
3865 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3866 /* we don't support these - and CANCEL_LOCK makes w2k
3867 and XP reboot so I don't really want to be
3868 compatible! (tridge) */
3869 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3872 /* Check if this is an oplock break on a file
3873 we have granted an oplock on.
3875 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3876 /* Client can insist on breaking to none. */
3877 BOOL break_to_none = (oplocklevel == 0);
3879 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3880 (unsigned int)oplocklevel, fsp->fnum ));
3883 * Make sure we have granted an exclusive or batch oplock on this file.
3886 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3887 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3888 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3890 /* if this is a pure oplock break request then don't send a reply */
3891 if (num_locks == 0 && num_ulocks == 0) {
3892 END_PROFILE(SMBlockingX);
3895 END_PROFILE(SMBlockingX);
3896 return ERROR_DOS(ERRDOS,ERRlock);
3900 if (remove_oplock(fsp, break_to_none) == False) {
3901 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3905 /* if this is a pure oplock break request then don't send a reply */
3906 if (num_locks == 0 && num_ulocks == 0) {
3907 /* Sanity check - ensure a pure oplock break is not a
3909 if(CVAL(inbuf,smb_vwv0) != 0xff)
3910 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3911 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3912 END_PROFILE(SMBlockingX);
3918 * We do this check *after* we have checked this is not a oplock break
3919 * response message. JRA.
3922 release_level_2_oplocks_on_change(fsp);
3924 /* Data now points at the beginning of the list
3925 of smb_unlkrng structs */
3926 for(i = 0; i < (int)num_ulocks; i++) {
3927 lock_pid = get_lock_pid( data, i, large_file_format);
3928 count = get_lock_count( data, i, large_file_format);
3929 offset = get_lock_offset( data, i, large_file_format, &err);
3932 * There is no error code marked "stupid client bug".... :-).
3935 END_PROFILE(SMBlockingX);
3936 return ERROR_DOS(ERRDOS,ERRnoaccess);
3939 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3940 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3942 status = do_unlock(fsp,conn,lock_pid,count,offset);
3943 if (NT_STATUS_V(status)) {
3944 END_PROFILE(SMBlockingX);
3945 return ERROR_NT(status);
3949 /* Setup the timeout in seconds. */
3951 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3953 /* Now do any requested locks */
3954 data += ((large_file_format ? 20 : 10)*num_ulocks);
3956 /* Data now points at the beginning of the list
3957 of smb_lkrng structs */
3959 for(i = 0; i < (int)num_locks; i++) {
3960 lock_pid = get_lock_pid( data, i, large_file_format);
3961 count = get_lock_count( data, i, large_file_format);
3962 offset = get_lock_offset( data, i, large_file_format, &err);
3965 * There is no error code marked "stupid client bug".... :-).
3968 END_PROFILE(SMBlockingX);
3969 return ERROR_DOS(ERRDOS,ERRnoaccess);
3972 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3973 (double)offset, (double)count, (unsigned int)lock_pid,
3974 fsp->fsp_name, (int)lock_timeout ));
3976 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3977 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3978 if (NT_STATUS_V(status)) {
3979 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3981 * A blocking lock was requested. Package up
3982 * this smb into a queued request and push it
3983 * onto the blocking lock queue.
3985 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3986 END_PROFILE(SMBlockingX);
3994 /* If any of the above locks failed, then we must unlock
3995 all of the previous locks (X/Open spec). */
3996 if (i != num_locks && num_locks != 0) {
3998 * Ensure we don't do a remove on the lock that just failed,
3999 * as under POSIX rules, if we have a lock already there, we
4000 * will delete it (and we shouldn't) .....
4002 for(i--; i >= 0; i--) {
4003 lock_pid = get_lock_pid( data, i, large_file_format);
4004 count = get_lock_count( data, i, large_file_format);
4005 offset = get_lock_offset( data, i, large_file_format, &err);
4008 * There is no error code marked "stupid client bug".... :-).
4011 END_PROFILE(SMBlockingX);
4012 return ERROR_DOS(ERRDOS,ERRnoaccess);
4015 do_unlock(fsp,conn,lock_pid,count,offset);
4017 END_PROFILE(SMBlockingX);
4018 return ERROR_NT(status);
4021 set_message(outbuf,2,0,True);
4023 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4024 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4026 END_PROFILE(SMBlockingX);
4027 return chain_reply(inbuf,outbuf,length,bufsize);
4030 /****************************************************************************
4031 Reply to a SMBreadbmpx (read block multiplex) request.
4032 ****************************************************************************/
4034 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4045 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4046 START_PROFILE(SMBreadBmpx);
4048 /* this function doesn't seem to work - disable by default */
4049 if (!lp_readbmpx()) {
4050 END_PROFILE(SMBreadBmpx);
4051 return ERROR_DOS(ERRSRV,ERRuseSTD);
4054 outsize = set_message(outbuf,8,0,True);
4056 CHECK_FSP(fsp,conn);
4059 startpos = IVAL(inbuf,smb_vwv1);
4060 maxcount = SVAL(inbuf,smb_vwv3);
4062 data = smb_buf(outbuf);
4063 pad = ((long)data)%4;
4068 max_per_packet = bufsize-(outsize+pad);
4072 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4073 END_PROFILE(SMBreadBmpx);
4074 return ERROR_DOS(ERRDOS,ERRlock);
4078 size_t N = MIN(max_per_packet,tcount-total_read);
4080 nread = read_file(fsp,data,startpos,N);
4085 if (nread < (ssize_t)N)
4086 tcount = total_read + nread;
4088 set_message(outbuf,8,nread,False);
4089 SIVAL(outbuf,smb_vwv0,startpos);
4090 SSVAL(outbuf,smb_vwv2,tcount);
4091 SSVAL(outbuf,smb_vwv6,nread);
4092 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4094 if (!send_smb(smbd_server_fd(),outbuf))
4095 exit_server("reply_readbmpx: send_smb failed.");
4097 total_read += nread;
4099 } while (total_read < (ssize_t)tcount);
4101 END_PROFILE(SMBreadBmpx);
4105 /****************************************************************************
4106 Reply to a SMBsetattrE.
4107 ****************************************************************************/
4109 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4111 struct utimbuf unix_times;
4113 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4114 START_PROFILE(SMBsetattrE);
4116 outsize = set_message(outbuf,0,0,True);
4118 if(!fsp || (fsp->conn != conn)) {
4119 END_PROFILE(SMBgetattrE);
4120 return ERROR_DOS(ERRDOS,ERRbadfid);
4124 * Convert the DOS times into unix times. Ignore create
4125 * time as UNIX can't set this.
4128 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4129 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4132 * Patch from Ray Frush <frush@engr.colostate.edu>
4133 * Sometimes times are sent as zero - ignore them.
4136 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4137 /* Ignore request */
4138 if( DEBUGLVL( 3 ) ) {
4139 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4140 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4142 END_PROFILE(SMBsetattrE);
4144 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4145 /* set modify time = to access time if modify time was 0 */
4146 unix_times.modtime = unix_times.actime;
4149 /* Set the date on this file */
4150 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4151 END_PROFILE(SMBsetattrE);
4152 return ERROR_DOS(ERRDOS,ERRnoaccess);
4155 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4156 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4158 END_PROFILE(SMBsetattrE);
4163 /* Back from the dead for OS/2..... JRA. */
4165 /****************************************************************************
4166 Reply to a SMBwritebmpx (write block multiplex primary) request.
4167 ****************************************************************************/
4169 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4172 ssize_t nwritten = -1;
4179 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4180 START_PROFILE(SMBwriteBmpx);
4182 CHECK_FSP(fsp,conn);
4186 tcount = SVAL(inbuf,smb_vwv1);
4187 startpos = IVAL(inbuf,smb_vwv3);
4188 write_through = BITSETW(inbuf+smb_vwv7,0);
4189 numtowrite = SVAL(inbuf,smb_vwv10);
4190 smb_doff = SVAL(inbuf,smb_vwv11);
4192 data = smb_base(inbuf) + smb_doff;
4194 /* If this fails we need to send an SMBwriteC response,
4195 not an SMBwritebmpx - set this up now so we don't forget */
4196 SCVAL(outbuf,smb_com,SMBwritec);
4198 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4199 END_PROFILE(SMBwriteBmpx);
4200 return(ERROR_DOS(ERRDOS,ERRlock));
4203 nwritten = write_file(fsp,data,startpos,numtowrite);
4205 if(lp_syncalways(SNUM(conn)) || write_through)
4206 sync_file(conn,fsp);
4208 if(nwritten < (ssize_t)numtowrite) {
4209 END_PROFILE(SMBwriteBmpx);
4210 return(UNIXERROR(ERRHRD,ERRdiskfull));
4213 /* If the maximum to be written to this file
4214 is greater than what we just wrote then set
4215 up a secondary struct to be attached to this
4216 fd, we will use this to cache error messages etc. */
4218 if((ssize_t)tcount > nwritten) {
4219 write_bmpx_struct *wbms;
4220 if(fsp->wbmpx_ptr != NULL)
4221 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4223 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4225 DEBUG(0,("Out of memory in reply_readmpx\n"));
4226 END_PROFILE(SMBwriteBmpx);
4227 return(ERROR_DOS(ERRSRV,ERRnoresource));
4229 wbms->wr_mode = write_through;
4230 wbms->wr_discard = False; /* No errors yet */
4231 wbms->wr_total_written = nwritten;
4232 wbms->wr_errclass = 0;
4234 fsp->wbmpx_ptr = wbms;
4237 /* We are returning successfully, set the message type back to
4239 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4241 outsize = set_message(outbuf,1,0,True);
4243 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4245 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4246 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4248 if (write_through && tcount==nwritten) {
4249 /* We need to send both a primary and a secondary response */
4250 smb_setlen(outbuf,outsize - 4);
4251 if (!send_smb(smbd_server_fd(),outbuf))
4252 exit_server("reply_writebmpx: send_smb failed.");
4254 /* Now the secondary */
4255 outsize = set_message(outbuf,1,0,True);
4256 SCVAL(outbuf,smb_com,SMBwritec);
4257 SSVAL(outbuf,smb_vwv0,nwritten);
4260 END_PROFILE(SMBwriteBmpx);
4264 /****************************************************************************
4265 Reply to a SMBwritebs (write block multiplex secondary) request.
4266 ****************************************************************************/
4268 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4271 ssize_t nwritten = -1;
4278 write_bmpx_struct *wbms;
4279 BOOL send_response = False;
4280 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4281 START_PROFILE(SMBwriteBs);
4283 CHECK_FSP(fsp,conn);
4286 tcount = SVAL(inbuf,smb_vwv1);
4287 startpos = IVAL(inbuf,smb_vwv2);
4288 numtowrite = SVAL(inbuf,smb_vwv6);
4289 smb_doff = SVAL(inbuf,smb_vwv7);
4291 data = smb_base(inbuf) + smb_doff;
4293 /* We need to send an SMBwriteC response, not an SMBwritebs */
4294 SCVAL(outbuf,smb_com,SMBwritec);
4296 /* This fd should have an auxiliary struct attached,
4297 check that it does */
4298 wbms = fsp->wbmpx_ptr;
4300 END_PROFILE(SMBwriteBs);
4304 /* If write through is set we can return errors, else we must cache them */
4305 write_through = wbms->wr_mode;
4307 /* Check for an earlier error */
4308 if(wbms->wr_discard) {
4309 END_PROFILE(SMBwriteBs);
4310 return -1; /* Just discard the packet */
4313 nwritten = write_file(fsp,data,startpos,numtowrite);
4315 if(lp_syncalways(SNUM(conn)) || write_through)
4316 sync_file(conn,fsp);
4318 if (nwritten < (ssize_t)numtowrite) {
4320 /* We are returning an error - we can delete the aux struct */
4323 fsp->wbmpx_ptr = NULL;
4324 END_PROFILE(SMBwriteBs);
4325 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4327 END_PROFILE(SMBwriteBs);
4328 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4331 /* Increment the total written, if this matches tcount
4332 we can discard the auxiliary struct (hurrah !) and return a writeC */
4333 wbms->wr_total_written += nwritten;
4334 if(wbms->wr_total_written >= tcount) {
4335 if (write_through) {
4336 outsize = set_message(outbuf,1,0,True);
4337 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4338 send_response = True;
4342 fsp->wbmpx_ptr = NULL;
4346 END_PROFILE(SMBwriteBs);
4350 END_PROFILE(SMBwriteBs);
4354 /****************************************************************************
4355 Reply to a SMBgetattrE.
4356 ****************************************************************************/
4358 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4360 SMB_STRUCT_STAT sbuf;
4363 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4364 START_PROFILE(SMBgetattrE);
4366 outsize = set_message(outbuf,11,0,True);
4368 if(!fsp || (fsp->conn != conn)) {
4369 END_PROFILE(SMBgetattrE);
4370 return ERROR_DOS(ERRDOS,ERRbadfid);
4373 /* Do an fstat on this file */
4374 if(fsp_stat(fsp, &sbuf)) {
4375 END_PROFILE(SMBgetattrE);
4376 return(UNIXERROR(ERRDOS,ERRnoaccess));
4379 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4382 * Convert the times into dos times. Set create
4383 * date to be last modify date as UNIX doesn't save
4387 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4388 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4389 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4392 SIVAL(outbuf,smb_vwv6,0);
4393 SIVAL(outbuf,smb_vwv8,0);
4395 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4396 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4398 SSVAL(outbuf,smb_vwv10, mode);
4400 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4402 END_PROFILE(SMBgetattrE);