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
29 /* look in server.c for some explanation of these variables */
33 extern char magic_char;
34 extern BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern pstring global_myname;
38 extern int global_oplock_break;
39 unsigned int smb_echo_count = 0;
41 extern fstring remote_machine;
42 extern BOOL global_encrypted_passwords_negotiated;
45 /****************************************************************************
46 reply to an special message
47 ****************************************************************************/
49 int reply_special(char *inbuf,char *outbuf)
52 int msg_type = CVAL(inbuf,0);
53 int msg_flags = CVAL(inbuf,1);
56 extern fstring local_machine;
60 static BOOL already_got_session = False;
64 memset(outbuf,'\0',smb_size);
69 case 0x81: /* session request */
71 if (already_got_session) {
72 exit_server("multiple session request not permitted");
77 if (name_len(inbuf+4) > 50 ||
78 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
79 DEBUG(0,("Invalid name length in session request\n"));
82 name_extract(inbuf,4,name1);
83 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
84 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
87 fstrcpy(remote_machine,name2);
88 remote_machine[15] = 0;
89 trim_string(remote_machine," "," ");
90 strlower(remote_machine);
91 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
93 fstrcpy(local_machine,name1);
94 len = strlen(local_machine);
96 name_type = local_machine[15];
97 local_machine[15] = 0;
99 trim_string(local_machine," "," ");
100 strlower(local_machine);
101 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
103 DEBUG(2,("netbios connect: local=%s remote=%s\n",
104 local_machine, remote_machine ));
106 if (name_type == 'R') {
107 /* We are being asked for a pathworks session ---
109 SCVAL(outbuf, 0,0x83);
113 /* only add the client's machine name to the list
114 of possibly valid usernames if we are operating
115 in share mode security */
116 if (lp_security() == SEC_SHARE) {
117 add_session_user(remote_machine);
120 reload_services(True);
123 claim_connection(NULL,"",MAXSTATUS,True);
125 already_got_session = True;
128 case 0x89: /* session keepalive request
129 (some old clients produce this?) */
130 SCVAL(outbuf,0,SMBkeepalive);
134 case 0x82: /* positive session response */
135 case 0x83: /* negative session response */
136 case 0x84: /* retarget session response */
137 DEBUG(0,("Unexpected session response\n"));
140 case SMBkeepalive: /* session keepalive */
145 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
146 msg_type, msg_flags));
152 /****************************************************************************
154 ****************************************************************************/
156 int reply_tcon(connection_struct *conn,
157 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
164 uint16 vuid = SVAL(inbuf,smb_uid);
168 DATA_BLOB password_blob;
170 START_PROFILE(SMBtcon);
172 *service_buf = *password = *dev = 0;
174 p = smb_buf(inbuf)+1;
175 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
176 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
178 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
180 p = strrchr_m(service_buf,'\\');
184 service = service_buf;
187 password_blob = data_blob(password, pwlen+1);
189 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
191 data_blob_clear_free(&password_blob);
194 END_PROFILE(SMBtcon);
195 return ERROR_NT(nt_status);
198 outsize = set_message(outbuf,2,0,True);
199 SSVAL(outbuf,smb_vwv0,max_recv);
200 SSVAL(outbuf,smb_vwv1,conn->cnum);
201 SSVAL(outbuf,smb_tid,conn->cnum);
203 DEBUG(3,("tcon service=%s cnum=%d\n",
204 service, conn->cnum));
206 END_PROFILE(SMBtcon);
210 /****************************************************************************
211 Reply to a tcon and X.
212 ****************************************************************************/
214 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
220 uint16 vuid = SVAL(inbuf,smb_uid);
221 int passlen = SVAL(inbuf,smb_vwv3);
224 extern BOOL global_encrypted_passwords_negotiated;
225 START_PROFILE(SMBtconX);
227 *service = *devicename = 0;
229 /* we might have to close an old one */
230 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
231 close_cnum(conn,vuid);
234 if (passlen > MAX_PASS_LEN) {
235 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
238 if (global_encrypted_passwords_negotiated) {
239 password = data_blob(smb_buf(inbuf),passlen);
241 password = data_blob(smb_buf(inbuf),passlen+1);
242 /* Ensure correct termination */
243 password.data[passlen]=0;
246 p = smb_buf(inbuf) + passlen;
247 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
250 * the service name can be either: \\server\share
251 * or share directly like on the DELL PowerVault 705
254 q = strchr_m(path+2,'\\');
256 END_PROFILE(SMBtconX);
257 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
259 fstrcpy(service,q+1);
262 fstrcpy(service,path);
264 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
266 DEBUG(4,("Got device type %s\n",devicename));
268 conn = make_connection(service,password,devicename,vuid,&nt_status);
270 data_blob_clear_free(&password);
273 END_PROFILE(SMBtconX);
274 return ERROR_NT(nt_status);
277 if (Protocol < PROTOCOL_NT1) {
278 set_message(outbuf,2,0,True);
280 p += srvstr_push(outbuf, p, devicename, -1,
281 STR_TERMINATE|STR_ASCII);
282 set_message_end(outbuf,p);
284 /* NT sets the fstype of IPC$ to the null string */
285 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
287 set_message(outbuf,3,0,True);
290 p += srvstr_push(outbuf, p, devicename, -1,
291 STR_TERMINATE|STR_ASCII);
292 p += srvstr_push(outbuf, p, fsname, -1,
295 set_message_end(outbuf,p);
297 /* what does setting this bit do? It is set by NT4 and
298 may affect the ability to autorun mounted cdroms */
299 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
300 (lp_csc_policy(SNUM(conn)) << 2));
302 init_dfsroot(conn, inbuf, outbuf);
306 DEBUG(3,("tconX service=%s \n",
309 /* set the incoming and outgoing tid to the just created one */
310 SSVAL(inbuf,smb_tid,conn->cnum);
311 SSVAL(outbuf,smb_tid,conn->cnum);
313 END_PROFILE(SMBtconX);
314 return chain_reply(inbuf,outbuf,length,bufsize);
318 /****************************************************************************
319 reply to an unknown type
320 ****************************************************************************/
321 int reply_unknown(char *inbuf,char *outbuf)
324 type = CVAL(inbuf,smb_com);
326 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
327 smb_fn_name(type), type, type));
329 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
333 /****************************************************************************
335 ****************************************************************************/
336 int reply_ioctl(connection_struct *conn,
337 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
339 uint16 device = SVAL(inbuf,smb_vwv1);
340 uint16 function = SVAL(inbuf,smb_vwv2);
341 uint32 ioctl_code = (device << 16) + function;
342 int replysize, outsize;
344 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
345 START_PROFILE(SMBioctl);
347 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
351 case IOCTL_QUERY_JOB_INFO:
355 END_PROFILE(SMBioctl);
356 return(ERROR_DOS(ERRSRV,ERRnosupport));
359 outsize = set_message(outbuf,8,replysize+1,True);
360 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
361 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
362 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
363 p = smb_buf(outbuf) + 1; /* Allow for alignment */
367 case IOCTL_QUERY_JOB_INFO:
369 uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
370 SSVAL(p,0,rap_jobid); /* Job number */
371 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
372 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
377 END_PROFILE(SMBioctl);
381 /****************************************************************************
383 ****************************************************************************/
384 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
390 BOOL bad_path = False;
391 SMB_STRUCT_STAT sbuf;
392 START_PROFILE(SMBchkpth);
394 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
396 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
398 unix_convert(name,conn,0,&bad_path,&sbuf);
400 mode = SVAL(inbuf,smb_vwv0);
402 if (check_name(name,conn)) {
403 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
404 ok = S_ISDIR(sbuf.st_mode);
408 /* We special case this - as when a Windows machine
409 is parsing a path is steps through the components
410 one at a time - if a component fails it expects
411 ERRbadpath, not ERRbadfile.
413 if(errno == ENOENT) {
414 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
417 return(UNIXERROR(ERRDOS,ERRbadpath));
420 outsize = set_message(outbuf,0,0,True);
422 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
424 END_PROFILE(SMBchkpth);
429 /****************************************************************************
431 ****************************************************************************/
432 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
436 SMB_STRUCT_STAT sbuf;
441 BOOL bad_path = False;
443 START_PROFILE(SMBgetatr);
445 p = smb_buf(inbuf) + 1;
446 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
448 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
450 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
451 under WfWg - weird! */
454 mode = aHIDDEN | aDIR;
455 if (!CAN_WRITE(conn)) mode |= aRONLY;
462 unix_convert(fname,conn,0,&bad_path,&sbuf);
463 if (check_name(fname,conn))
465 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
467 mode = dos_mode(conn,fname,&sbuf);
469 mtime = sbuf.st_mtime;
475 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
481 set_bad_path_error(errno, bad_path);
482 END_PROFILE(SMBgetatr);
483 return(UNIXERROR(ERRDOS,ERRbadfile));
486 outsize = set_message(outbuf,10,0,True);
488 SSVAL(outbuf,smb_vwv0,mode);
489 if(lp_dos_filetime_resolution(SNUM(conn)) )
490 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
492 put_dos_date3(outbuf,smb_vwv1,mtime);
493 SIVAL(outbuf,smb_vwv3,(uint32)size);
495 if (Protocol >= PROTOCOL_NT1)
496 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
498 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
500 END_PROFILE(SMBgetatr);
505 /****************************************************************************
507 ****************************************************************************/
508 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
515 SMB_STRUCT_STAT sbuf;
516 BOOL bad_path = False;
519 START_PROFILE(SMBsetatr);
521 p = smb_buf(inbuf) + 1;
522 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
523 unix_convert(fname,conn,0,&bad_path,&sbuf);
525 mode = SVAL(inbuf,smb_vwv0);
526 mtime = make_unix_date3(inbuf+smb_vwv1);
528 if (VALID_STAT_OF_DIR(sbuf))
533 if (check_name(fname,conn))
534 ok = (file_chmod(conn,fname,mode,NULL) == 0);
536 ok = set_filetime(conn,fname,mtime);
540 set_bad_path_error(errno, bad_path);
541 END_PROFILE(SMBsetatr);
542 return(UNIXERROR(ERRDOS,ERRnoaccess));
545 outsize = set_message(outbuf,0,0,True);
547 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
549 END_PROFILE(SMBsetatr);
554 /****************************************************************************
556 ****************************************************************************/
557 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
560 SMB_BIG_UINT dfree,dsize,bsize;
561 START_PROFILE(SMBdskattr);
563 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
565 outsize = set_message(outbuf,5,0,True);
567 if (Protocol <= PROTOCOL_LANMAN2) {
568 double total_space, free_space;
569 /* we need to scale this to a number that DOS6 can handle. We
570 use floating point so we can handle large drives on systems
571 that don't have 64 bit integers
573 we end up displaying a maximum of 2G to DOS systems
575 total_space = dsize * (double)bsize;
576 free_space = dfree * (double)bsize;
578 dsize = (total_space+63*512) / (64*512);
579 dfree = (free_space+63*512) / (64*512);
581 if (dsize > 0xFFFF) dsize = 0xFFFF;
582 if (dfree > 0xFFFF) dfree = 0xFFFF;
584 SSVAL(outbuf,smb_vwv0,dsize);
585 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
586 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
587 SSVAL(outbuf,smb_vwv3,dfree);
589 SSVAL(outbuf,smb_vwv0,dsize);
590 SSVAL(outbuf,smb_vwv1,bsize/512);
591 SSVAL(outbuf,smb_vwv2,512);
592 SSVAL(outbuf,smb_vwv3,dfree);
595 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
597 END_PROFILE(SMBdskattr);
602 /****************************************************************************
604 Can be called from SMBsearch, SMBffirst or SMBfunique.
605 ****************************************************************************/
606 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
617 BOOL finished = False;
626 BOOL check_descend = False;
627 BOOL expect_close = False;
628 BOOL can_open = True;
629 BOOL bad_path = False;
630 START_PROFILE(SMBsearch);
632 *mask = *directory = *fname = 0;
634 /* If we were called as SMBffirst then we must expect close. */
635 if(CVAL(inbuf,smb_com) == SMBffirst)
638 outsize = set_message(outbuf,1,3,True);
639 maxentries = SVAL(inbuf,smb_vwv0);
640 dirtype = SVAL(inbuf,smb_vwv1);
641 p = smb_buf(inbuf) + 1;
642 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
644 status_len = SVAL(p, 0);
647 /* dirtype &= ~aDIR; */
651 SMB_STRUCT_STAT sbuf;
654 pstrcpy(directory,path);
656 unix_convert(directory,conn,0,&bad_path,&sbuf);
659 if (!check_name(directory,conn))
662 p = strrchr_m(dir2,'/');
674 p = strrchr_m(directory,'/');
680 if (strlen(directory) == 0)
681 pstrcpy(directory,"./");
682 memset((char *)status,'\0',21);
683 SCVAL(status,0,dirtype);
688 dirtype = CVAL(status,0) & 0x1F;
689 conn->dirptr = dptr_fetch(status+12,&dptr_num);
692 string_set(&conn->dirpath,dptr_path(dptr_num));
693 fstrcpy(mask, dptr_wcard(dptr_num));
698 p = smb_buf(outbuf) + 3;
704 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
709 set_bad_path_error(errno, bad_path);
710 END_PROFILE(SMBsearch);
711 return (UNIXERROR(ERRDOS,ERRnofids));
713 END_PROFILE(SMBsearch);
714 return ERROR_DOS(ERRDOS,ERRnofids);
716 dptr_set_wcard(dptr_num, strdup(mask));
719 DEBUG(4,("dptr_num is %d\n",dptr_num));
723 if ((dirtype&0x1F) == aVOLID)
726 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
727 dptr_fill(p+12,dptr_num);
728 if (dptr_zero(p+12) && (status_len==0))
732 p += DIR_STRUCT_SIZE;
736 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
737 conn->dirpath,lp_dontdescend(SNUM(conn))));
738 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
739 check_descend = True;
741 for (i=numentries;(i<maxentries) && !finished;i++)
744 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
748 make_dir_struct(p,mask,fname,size,mode,date);
749 dptr_fill(p+12,dptr_num);
752 p += DIR_STRUCT_SIZE;
761 if (numentries == 0 || !ok)
763 SCVAL(outbuf,smb_rcls,ERRDOS);
764 SSVAL(outbuf,smb_err,ERRnofiles);
765 dptr_close(&dptr_num);
768 /* If we were called as SMBffirst with smb_search_id == NULL
769 and no entries were found then return error and close dirptr
772 if(ok && expect_close && numentries == 0 && status_len == 0)
774 SCVAL(outbuf,smb_rcls,ERRDOS);
775 SSVAL(outbuf,smb_err,ERRnofiles);
776 /* Also close the dptr - we know it's gone */
777 dptr_close(&dptr_num);
780 /* If we were called as SMBfunique, then we can close the dirptr now ! */
781 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
782 dptr_close(&dptr_num);
784 SSVAL(outbuf,smb_vwv0,numentries);
785 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
786 SCVAL(smb_buf(outbuf),0,5);
787 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
789 if (Protocol >= PROTOCOL_NT1)
790 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
792 outsize += DIR_STRUCT_SIZE*numentries;
793 smb_setlen(outbuf,outsize - 4);
795 if ((! *directory) && dptr_path(dptr_num))
796 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
798 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
799 smb_fn_name(CVAL(inbuf,smb_com)),
800 mask, directory, dirtype, numentries, maxentries ) );
802 END_PROFILE(SMBsearch);
807 /****************************************************************************
808 reply to a fclose (stop directory search)
809 ****************************************************************************/
810 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
819 START_PROFILE(SMBfclose);
821 outsize = set_message(outbuf,1,0,True);
822 p = smb_buf(inbuf) + 1;
823 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
825 status_len = SVAL(p,0);
828 if (status_len == 0) {
829 END_PROFILE(SMBfclose);
830 return ERROR_DOS(ERRSRV,ERRsrverror);
835 if(dptr_fetch(status+12,&dptr_num)) {
836 /* Close the dptr - we know it's gone */
837 dptr_close(&dptr_num);
840 SSVAL(outbuf,smb_vwv0,0);
842 DEBUG(3,("search close\n"));
844 END_PROFILE(SMBfclose);
849 /****************************************************************************
851 ****************************************************************************/
853 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
863 SMB_STRUCT_STAT sbuf;
864 BOOL bad_path = False;
866 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
867 START_PROFILE(SMBopen);
869 share_mode = SVAL(inbuf,smb_vwv0);
871 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
873 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
875 unix_convert(fname,conn,0,&bad_path,&sbuf);
877 unixmode = unix_mode(conn,aARCH,fname);
879 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
880 unixmode, oplock_request,&rmode,NULL);
884 set_bad_path_error(errno, bad_path);
885 END_PROFILE(SMBopen);
886 return(UNIXERROR(ERRDOS,ERRnoaccess));
890 fmode = dos_mode(conn,fname,&sbuf);
891 mtime = sbuf.st_mtime;
894 DEBUG(3,("attempt to open a directory %s\n",fname));
895 close_file(fsp,False);
896 END_PROFILE(SMBopen);
897 return ERROR_DOS(ERRDOS,ERRnoaccess);
900 outsize = set_message(outbuf,7,0,True);
901 SSVAL(outbuf,smb_vwv0,fsp->fnum);
902 SSVAL(outbuf,smb_vwv1,fmode);
903 if(lp_dos_filetime_resolution(SNUM(conn)) )
904 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
906 put_dos_date3(outbuf,smb_vwv2,mtime);
907 SIVAL(outbuf,smb_vwv4,(uint32)size);
908 SSVAL(outbuf,smb_vwv6,rmode);
910 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
911 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
914 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
915 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
916 END_PROFILE(SMBopen);
921 /****************************************************************************
922 reply to an open and X
923 ****************************************************************************/
924 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
927 int smb_mode = SVAL(inbuf,smb_vwv3);
928 int smb_attr = SVAL(inbuf,smb_vwv5);
929 /* Breakout the oplock request bits so we can set the
930 reply bits separately. */
931 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
932 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
933 BOOL oplock_request = ex_oplock_request | core_oplock_request;
935 int open_flags = SVAL(inbuf,smb_vwv2);
936 int smb_sattr = SVAL(inbuf,smb_vwv4);
937 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
939 int smb_ofun = SVAL(inbuf,smb_vwv8);
942 int fmode=0,mtime=0,rmode=0;
943 SMB_STRUCT_STAT sbuf;
945 BOOL bad_path = False;
947 START_PROFILE(SMBopenX);
949 /* If it's an IPC, pass off the pipe handler. */
951 if (lp_nt_pipe_support()) {
952 END_PROFILE(SMBopenX);
953 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
955 END_PROFILE(SMBopenX);
956 return ERROR_DOS(ERRSRV,ERRaccess);
960 /* XXXX we need to handle passed times, sattr and flags */
961 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
963 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
965 unix_convert(fname,conn,0,&bad_path,&sbuf);
967 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
969 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
970 oplock_request, &rmode,&smb_action);
974 set_bad_path_error(errno, bad_path);
975 END_PROFILE(SMBopenX);
976 return(UNIXERROR(ERRDOS,ERRnoaccess));
980 fmode = dos_mode(conn,fname,&sbuf);
981 mtime = sbuf.st_mtime;
983 close_file(fsp,False);
984 END_PROFILE(SMBopenX);
985 return ERROR_DOS(ERRDOS,ERRnoaccess);
988 /* If the caller set the extended oplock request bit
989 and we granted one (by whatever means) - set the
990 correct bit for extended oplock reply.
993 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
994 smb_action |= EXTENDED_OPLOCK_GRANTED;
997 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
998 smb_action |= EXTENDED_OPLOCK_GRANTED;
1001 /* If the caller set the core oplock request bit
1002 and we granted one (by whatever means) - set the
1003 correct bit for core oplock reply.
1006 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1007 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1010 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1011 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1014 set_message(outbuf,15,0,True);
1015 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1016 SSVAL(outbuf,smb_vwv3,fmode);
1017 if(lp_dos_filetime_resolution(SNUM(conn)) )
1018 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1020 put_dos_date3(outbuf,smb_vwv4,mtime);
1021 SIVAL(outbuf,smb_vwv6,(uint32)size);
1022 SSVAL(outbuf,smb_vwv8,rmode);
1023 SSVAL(outbuf,smb_vwv11,smb_action);
1025 END_PROFILE(SMBopenX);
1026 return chain_reply(inbuf,outbuf,length,bufsize);
1030 /****************************************************************************
1031 reply to a SMBulogoffX
1032 ****************************************************************************/
1033 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1035 uint16 vuid = SVAL(inbuf,smb_uid);
1036 user_struct *vuser = get_valid_user_struct(vuid);
1037 START_PROFILE(SMBulogoffX);
1040 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1043 /* in user level security we are supposed to close any files
1044 open by this user */
1045 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1046 file_close_user(vuid);
1049 invalidate_vuid(vuid);
1051 set_message(outbuf,2,0,True);
1053 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1055 END_PROFILE(SMBulogoffX);
1056 return chain_reply(inbuf,outbuf,length,bufsize);
1060 /****************************************************************************
1061 reply to a mknew or a create
1062 ****************************************************************************/
1063 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1071 BOOL bad_path = False;
1073 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1074 SMB_STRUCT_STAT sbuf;
1075 START_PROFILE(SMBcreate);
1077 com = SVAL(inbuf,smb_com);
1079 createmode = SVAL(inbuf,smb_vwv0);
1080 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1082 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1084 unix_convert(fname,conn,0,&bad_path,&sbuf);
1086 if (createmode & aVOLID) {
1087 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1090 unixmode = unix_mode(conn,createmode,fname);
1094 /* We should fail if file exists. */
1095 ofun = FILE_CREATE_IF_NOT_EXIST;
1099 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1100 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1103 /* Open file in dos compatibility share mode. */
1104 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1105 ofun, unixmode, oplock_request, NULL, NULL);
1109 set_bad_path_error(errno, bad_path);
1110 END_PROFILE(SMBcreate);
1111 return(UNIXERROR(ERRDOS,ERRnoaccess));
1114 outsize = set_message(outbuf,1,0,True);
1115 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1117 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1118 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1121 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1122 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1124 DEBUG( 2, ( "new file %s\n", fname ) );
1125 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1126 fname, fsp->fd, createmode, (int)unixmode ) );
1128 END_PROFILE(SMBcreate);
1133 /****************************************************************************
1134 reply to a create temporary file
1135 ****************************************************************************/
1136 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1142 BOOL bad_path = False;
1144 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1146 SMB_STRUCT_STAT sbuf;
1149 START_PROFILE(SMBctemp);
1151 createmode = SVAL(inbuf,smb_vwv0);
1152 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1153 pstrcat(fname,"\\TMXXXXXX");
1155 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1157 unix_convert(fname,conn,0,&bad_path,&sbuf);
1159 unixmode = unix_mode(conn,createmode,fname);
1161 tmpfd = smb_mkstemp(fname);
1163 END_PROFILE(SMBctemp);
1164 return(UNIXERROR(ERRDOS,ERRnoaccess));
1167 vfs_stat(conn,fname,&sbuf);
1169 /* Open file in dos compatibility share mode. */
1170 /* We should fail if file does not exist. */
1171 fsp = open_file_shared(conn,fname,&sbuf,
1172 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1173 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1174 unixmode, oplock_request, NULL, NULL);
1176 /* close fd from smb_mkstemp() */
1180 set_bad_path_error(errno, bad_path);
1181 END_PROFILE(SMBctemp);
1182 return(UNIXERROR(ERRDOS,ERRnoaccess));
1185 outsize = set_message(outbuf,1,0,True);
1186 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1188 /* the returned filename is relative to the directory */
1189 s = strrchr_m(fname, '/');
1196 p = smb_buf(outbuf);
1197 SSVALS(p, 0, -1); /* what is this? not in spec */
1198 SSVAL(p, 2, strlen(s));
1200 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1201 outsize = set_message_end(outbuf, p);
1203 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1204 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1207 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1208 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1210 DEBUG( 2, ( "created temp file %s\n", fname ) );
1211 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1212 fname, fsp->fd, createmode, (int)unixmode ) );
1214 END_PROFILE(SMBctemp);
1218 /*******************************************************************
1219 Check if a user is allowed to rename a file.
1220 ********************************************************************/
1222 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1228 if (!CAN_WRITE(conn))
1229 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1231 if (S_ISDIR(pst->st_mode))
1232 return NT_STATUS_OK;
1234 /* We need a better way to return NT status codes from open... */
1238 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1239 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1242 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1243 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1244 ret = NT_STATUS_SHARING_VIOLATION;
1249 close_file(fsp,False);
1250 return NT_STATUS_OK;
1253 /*******************************************************************
1254 Check if a user is allowed to delete a file.
1255 ********************************************************************/
1257 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1259 SMB_STRUCT_STAT sbuf;
1265 if (!CAN_WRITE(conn))
1266 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1268 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1269 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1271 fmode = dos_mode(conn,fname,&sbuf);
1273 return NT_STATUS_FILE_IS_A_DIRECTORY;
1274 if (!lp_delete_readonly(SNUM(conn))) {
1276 return NT_STATUS_CANNOT_DELETE;
1278 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1279 return NT_STATUS_CANNOT_DELETE;
1281 /* We need a better way to return NT status codes from open... */
1285 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1286 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1289 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1290 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1291 ret = NT_STATUS_SHARING_VIOLATION;
1296 close_file(fsp,False);
1297 return NT_STATUS_OK;
1300 /****************************************************************************
1301 The guts of the unlink command, split out so it may be called by the NT SMB
1303 ****************************************************************************/
1305 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1311 NTSTATUS error = NT_STATUS_OK;
1313 BOOL bad_path = False;
1315 SMB_STRUCT_STAT sbuf;
1317 *directory = *mask = 0;
1319 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1321 p = strrchr_m(name,'/');
1323 pstrcpy(directory,".");
1327 pstrcpy(directory,name);
1332 * We should only check the mangled cache
1333 * here if unix_convert failed. This means
1334 * that the path in 'mask' doesn't exist
1335 * on the file system and so we need to look
1336 * for a possible mangle. This patch from
1337 * Tine Smukavec <valentin.smukavec@hermes.si>.
1340 if (!rc && mangle_is_mangled(mask))
1341 mangle_check_cache( mask );
1343 has_wild = ms_has_wild(mask);
1346 pstrcat(directory,"/");
1347 pstrcat(directory,mask);
1348 error = can_delete(directory,conn,dirtype);
1349 if (!NT_STATUS_IS_OK(error)) return error;
1351 if (vfs_unlink(conn,directory) == 0) {
1355 void *dirptr = NULL;
1358 if (check_name(directory,conn))
1359 dirptr = OpenDir(conn, directory, True);
1361 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1362 the pattern matches against the long name, otherwise the short name
1363 We don't implement this yet XXXX
1367 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1369 if (strequal(mask,"????????.???"))
1372 while ((dname = ReadDirName(dirptr))) {
1374 pstrcpy(fname,dname);
1376 if(!mask_match(fname, mask, case_sensitive)) continue;
1378 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1379 error = can_delete(fname,conn,dirtype);
1380 if (!NT_STATUS_IS_OK(error)) continue;
1381 if (vfs_unlink(conn,fname) == 0) count++;
1382 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1388 if (count == 0 && NT_STATUS_IS_OK(error)) {
1389 error = map_nt_error_from_unix(errno);
1395 /****************************************************************************
1397 ****************************************************************************/
1399 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1406 START_PROFILE(SMBunlink);
1408 dirtype = SVAL(inbuf,smb_vwv0);
1410 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1412 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1414 DEBUG(3,("reply_unlink : %s\n",name));
1416 status = unlink_internals(conn, dirtype, name);
1417 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1420 * Win2k needs a changenotify request response before it will
1421 * update after a rename..
1423 process_pending_change_notify_queue((time_t)0);
1425 outsize = set_message(outbuf,0,0,True);
1427 END_PROFILE(SMBunlink);
1431 /****************************************************************************
1433 ****************************************************************************/
1435 void fail_readraw(void)
1438 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1440 exit_server(errstr);
1443 /****************************************************************************
1444 Reply to a readbraw (core+ protocol).
1445 ****************************************************************************/
1447 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1449 ssize_t maxcount,mincount;
1452 char *header = outbuf;
1455 START_PROFILE(SMBreadbraw);
1458 * Special check if an oplock break has been issued
1459 * and the readraw request croses on the wire, we must
1460 * return a zero length response here.
1463 if(global_oplock_break) {
1464 _smb_setlen(header,0);
1465 if (write_data(smbd_server_fd(),header,4) != 4)
1467 DEBUG(5,("readbraw - oplock break finished\n"));
1468 END_PROFILE(SMBreadbraw);
1472 fsp = file_fsp(inbuf,smb_vwv0);
1474 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1476 * fsp could be NULL here so use the value from the packet. JRA.
1478 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1479 _smb_setlen(header,0);
1480 if (write_data(smbd_server_fd(),header,4) != 4)
1482 END_PROFILE(SMBreadbraw);
1486 CHECK_FSP(fsp,conn);
1488 flush_write_cache(fsp, READRAW_FLUSH);
1490 startpos = IVAL(inbuf,smb_vwv1);
1491 if(CVAL(inbuf,smb_wct) == 10) {
1493 * This is a large offset (64 bit) read.
1495 #ifdef LARGE_SMB_OFF_T
1497 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1499 #else /* !LARGE_SMB_OFF_T */
1502 * Ensure we haven't been sent a >32 bit offset.
1505 if(IVAL(inbuf,smb_vwv8) != 0) {
1506 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1507 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1508 _smb_setlen(header,0);
1509 if (write_data(smbd_server_fd(),header,4) != 4)
1511 END_PROFILE(SMBreadbraw);
1515 #endif /* LARGE_SMB_OFF_T */
1518 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1519 _smb_setlen(header,0);
1520 if (write_data(smbd_server_fd(),header,4) != 4)
1522 END_PROFILE(SMBreadbraw);
1526 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1527 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1529 /* ensure we don't overrun the packet size */
1530 maxcount = MIN(65535,maxcount);
1531 maxcount = MAX(mincount,maxcount);
1533 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1534 SMB_OFF_T size = fsp->size;
1535 SMB_OFF_T sizeneeded = startpos + maxcount;
1537 if (size < sizeneeded) {
1539 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1541 if (!fsp->can_write)
1545 if (startpos >= size)
1548 nread = MIN(maxcount,(size - startpos));
1551 if (nread < mincount)
1554 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1555 (int)maxcount, (int)mincount, (int)nread ) );
1558 ret = read_file(fsp,header+4,startpos,nread);
1563 _smb_setlen(header,ret);
1564 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
1567 DEBUG(5,("readbraw finished\n"));
1568 END_PROFILE(SMBreadbraw);
1572 /****************************************************************************
1573 reply to a lockread (core+ protocol)
1574 ****************************************************************************/
1575 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1583 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1584 START_PROFILE(SMBlockread);
1586 CHECK_FSP(fsp,conn);
1589 release_level_2_oplocks_on_change(fsp);
1591 numtoread = SVAL(inbuf,smb_vwv1);
1592 startpos = IVAL(inbuf,smb_vwv2);
1594 outsize = set_message(outbuf,5,3,True);
1595 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1596 data = smb_buf(outbuf) + 3;
1599 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1600 * protocol request that predates the read/write lock concept.
1601 * Thus instead of asking for a read lock here we need to ask
1602 * for a write lock. JRA.
1605 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1606 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1608 if (NT_STATUS_V(status)) {
1609 if (lp_blocking_locks(SNUM(conn))) {
1611 * A blocking lock was requested. Package up
1612 * this smb into a queued request and push it
1613 * onto the blocking lock queue.
1615 if(push_blocking_lock_request(inbuf, length, -1, 0))
1616 END_PROFILE(SMBlockread);
1619 END_PROFILE(SMBlockread);
1620 return ERROR_NT(status);
1623 nread = read_file(fsp,data,startpos,numtoread);
1626 END_PROFILE(SMBlockread);
1627 return(UNIXERROR(ERRDOS,ERRnoaccess));
1631 SSVAL(outbuf,smb_vwv0,nread);
1632 SSVAL(outbuf,smb_vwv5,nread+3);
1633 SSVAL(smb_buf(outbuf),1,nread);
1635 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1636 fsp->fnum, (int)numtoread, (int)nread));
1638 END_PROFILE(SMBlockread);
1643 /****************************************************************************
1645 ****************************************************************************/
1647 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1654 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1655 START_PROFILE(SMBread);
1657 CHECK_FSP(fsp,conn);
1660 numtoread = SVAL(inbuf,smb_vwv1);
1661 startpos = IVAL(inbuf,smb_vwv2);
1664 outsize = set_message(outbuf,5,3,True);
1665 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1666 data = smb_buf(outbuf) + 3;
1668 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1669 END_PROFILE(SMBread);
1670 return ERROR_DOS(ERRDOS,ERRlock);
1674 nread = read_file(fsp,data,startpos,numtoread);
1677 END_PROFILE(SMBread);
1678 return(UNIXERROR(ERRDOS,ERRnoaccess));
1682 SSVAL(outbuf,smb_vwv0,nread);
1683 SSVAL(outbuf,smb_vwv5,nread+3);
1684 SCVAL(smb_buf(outbuf),0,1);
1685 SSVAL(smb_buf(outbuf),1,nread);
1687 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1688 fsp->fnum, (int)numtoread, (int)nread ) );
1690 END_PROFILE(SMBread);
1695 /****************************************************************************
1696 reply to a read and X
1697 ****************************************************************************/
1698 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1700 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1701 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1702 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1703 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1706 START_PROFILE(SMBreadX);
1708 /* If it's an IPC, pass off the pipe handler. */
1710 END_PROFILE(SMBreadX);
1711 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1714 CHECK_FSP(fsp,conn);
1717 set_message(outbuf,12,0,True);
1718 data = smb_buf(outbuf);
1720 if(CVAL(inbuf,smb_wct) == 12) {
1721 #ifdef LARGE_SMB_OFF_T
1723 * This is a large offset (64 bit) read.
1725 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1727 #else /* !LARGE_SMB_OFF_T */
1730 * Ensure we haven't been sent a >32 bit offset.
1733 if(IVAL(inbuf,smb_vwv10) != 0) {
1734 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1735 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1736 END_PROFILE(SMBreadX);
1737 return ERROR_DOS(ERRDOS,ERRbadaccess);
1740 #endif /* LARGE_SMB_OFF_T */
1744 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1745 END_PROFILE(SMBreadX);
1746 return ERROR_DOS(ERRDOS,ERRlock);
1748 nread = read_file(fsp,data,startpos,smb_maxcnt);
1751 END_PROFILE(SMBreadX);
1752 return(UNIXERROR(ERRDOS,ERRnoaccess));
1755 SSVAL(outbuf,smb_vwv5,nread);
1756 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1757 SSVAL(smb_buf(outbuf),-2,nread);
1759 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
1760 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
1762 END_PROFILE(SMBreadX);
1763 return chain_reply(inbuf,outbuf,length,bufsize);
1766 /****************************************************************************
1767 reply to a writebraw (core+ or LANMAN1.0 protocol)
1768 ****************************************************************************/
1770 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1773 ssize_t total_written=0;
1774 size_t numtowrite=0;
1779 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1781 START_PROFILE(SMBwritebraw);
1783 CHECK_FSP(fsp,conn);
1786 tcount = IVAL(inbuf,smb_vwv1);
1787 startpos = IVAL(inbuf,smb_vwv3);
1788 write_through = BITSETW(inbuf+smb_vwv7,0);
1790 /* We have to deal with slightly different formats depending
1791 on whether we are using the core+ or lanman1.0 protocol */
1793 if(Protocol <= PROTOCOL_COREPLUS) {
1794 numtowrite = SVAL(smb_buf(inbuf),-2);
1795 data = smb_buf(inbuf);
1797 numtowrite = SVAL(inbuf,smb_vwv10);
1798 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1801 /* force the error type */
1802 SCVAL(inbuf,smb_com,SMBwritec);
1803 SCVAL(outbuf,smb_com,SMBwritec);
1805 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1806 END_PROFILE(SMBwritebraw);
1807 return(ERROR_DOS(ERRDOS,ERRlock));
1811 nwritten = write_file(fsp,data,startpos,numtowrite);
1813 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1814 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1816 if (nwritten < numtowrite) {
1817 END_PROFILE(SMBwritebraw);
1818 return(UNIXERROR(ERRHRD,ERRdiskfull));
1821 total_written = nwritten;
1823 /* Return a message to the redirector to tell it to send more bytes */
1824 SCVAL(outbuf,smb_com,SMBwritebraw);
1825 SSVALS(outbuf,smb_vwv0,-1);
1826 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1827 if (!send_smb(smbd_server_fd(),outbuf))
1828 exit_server("reply_writebraw: send_smb failed.");
1830 /* Now read the raw data into the buffer and write it */
1831 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1832 exit_server("secondary writebraw failed");
1835 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1836 numtowrite = smb_len(inbuf);
1838 /* Set up outbuf to return the correct return */
1839 outsize = set_message(outbuf,1,0,True);
1840 SCVAL(outbuf,smb_com,SMBwritec);
1841 SSVAL(outbuf,smb_vwv0,total_written);
1843 if (numtowrite != 0) {
1845 if (numtowrite > BUFFER_SIZE) {
1846 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1847 (unsigned int)numtowrite ));
1848 exit_server("secondary writebraw failed");
1851 if (tcount > nwritten+numtowrite) {
1852 DEBUG(3,("Client overestimated the write %d %d %d\n",
1853 (int)tcount,(int)nwritten,(int)numtowrite));
1856 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1857 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1859 exit_server("secondary writebraw failed");
1862 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1864 if (nwritten < (ssize_t)numtowrite) {
1865 SCVAL(outbuf,smb_rcls,ERRHRD);
1866 SSVAL(outbuf,smb_err,ERRdiskfull);
1870 total_written += nwritten;
1873 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1874 sync_file(conn,fsp);
1876 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1877 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1879 /* we won't return a status if write through is not selected - this follows what WfWg does */
1880 END_PROFILE(SMBwritebraw);
1881 if (!write_through && total_written==tcount) {
1883 #if RABBIT_PELLET_FIX
1885 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1886 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1888 if (!send_keepalive(smbd_server_fd()))
1889 exit_server("reply_writebraw: send of keepalive failed");
1897 /****************************************************************************
1898 reply to a writeunlock (core+)
1899 ****************************************************************************/
1901 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1902 int size, int dum_buffsize)
1904 ssize_t nwritten = -1;
1909 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1911 START_PROFILE(SMBwriteunlock);
1913 CHECK_FSP(fsp,conn);
1916 numtowrite = SVAL(inbuf,smb_vwv1);
1917 startpos = IVAL(inbuf,smb_vwv2);
1918 data = smb_buf(inbuf) + 3;
1920 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
1921 WRITE_LOCK,False)) {
1922 END_PROFILE(SMBwriteunlock);
1923 return ERROR_DOS(ERRDOS,ERRlock);
1926 /* The special X/Open SMB protocol handling of
1927 zero length writes is *NOT* done for
1932 nwritten = write_file(fsp,data,startpos,numtowrite);
1934 if (lp_syncalways(SNUM(conn)))
1935 sync_file(conn,fsp);
1937 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
1938 END_PROFILE(SMBwriteunlock);
1939 return(UNIXERROR(ERRDOS,ERRnoaccess));
1942 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
1943 (SMB_BIG_UINT)startpos);
1944 if (NT_STATUS_V(status)) {
1945 END_PROFILE(SMBwriteunlock);
1946 return ERROR_NT(status);
1949 outsize = set_message(outbuf,1,0,True);
1951 SSVAL(outbuf,smb_vwv0,nwritten);
1953 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
1954 fsp->fnum, (int)numtowrite, (int)nwritten));
1956 END_PROFILE(SMBwriteunlock);
1961 /****************************************************************************
1963 ****************************************************************************/
1965 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
1968 ssize_t nwritten = -1;
1971 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1973 START_PROFILE(SMBwrite);
1975 /* If it's an IPC, pass off the pipe handler. */
1977 END_PROFILE(SMBwrite);
1978 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
1981 CHECK_FSP(fsp,conn);
1984 numtowrite = SVAL(inbuf,smb_vwv1);
1985 startpos = IVAL(inbuf,smb_vwv2);
1986 data = smb_buf(inbuf) + 3;
1988 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1989 END_PROFILE(SMBwrite);
1990 return ERROR_DOS(ERRDOS,ERRlock);
1994 * X/Open SMB protocol says that if smb_vwv1 is
1995 * zero then the file size should be extended or
1996 * truncated to the size given in smb_vwv[2-3].
1999 if(numtowrite == 0) {
2001 * This is actually an allocate call, and set EOF. JRA.
2003 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2005 END_PROFILE(SMBwrite);
2006 return ERROR_NT(NT_STATUS_DISK_FULL);
2008 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2010 END_PROFILE(SMBwrite);
2011 return ERROR_NT(NT_STATUS_DISK_FULL);
2014 nwritten = write_file(fsp,data,startpos,numtowrite);
2016 if (lp_syncalways(SNUM(conn)))
2017 sync_file(conn,fsp);
2019 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2020 END_PROFILE(SMBwrite);
2021 return(UNIXERROR(ERRDOS,ERRnoaccess));
2024 outsize = set_message(outbuf,1,0,True);
2026 SSVAL(outbuf,smb_vwv0,nwritten);
2028 if (nwritten < (ssize_t)numtowrite) {
2029 SCVAL(outbuf,smb_rcls,ERRHRD);
2030 SSVAL(outbuf,smb_err,ERRdiskfull);
2033 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2035 END_PROFILE(SMBwrite);
2040 /****************************************************************************
2041 reply to a write and X
2042 ****************************************************************************/
2043 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2045 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2046 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2047 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2048 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2049 ssize_t nwritten = -1;
2050 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2051 unsigned int smblen = smb_len(inbuf);
2053 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2054 START_PROFILE(SMBwriteX);
2056 /* If it's an IPC, pass off the pipe handler. */
2058 END_PROFILE(SMBwriteX);
2059 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2062 CHECK_FSP(fsp,conn);
2065 /* Deal with possible LARGE_WRITEX */
2067 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2069 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2070 END_PROFILE(SMBwriteX);
2071 return ERROR_DOS(ERRDOS,ERRbadmem);
2074 data = smb_base(inbuf) + smb_doff;
2076 if(CVAL(inbuf,smb_wct) == 14) {
2077 #ifdef LARGE_SMB_OFF_T
2079 * This is a large offset (64 bit) write.
2081 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2083 #else /* !LARGE_SMB_OFF_T */
2086 * Ensure we haven't been sent a >32 bit offset.
2089 if(IVAL(inbuf,smb_vwv12) != 0) {
2090 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2091 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2092 END_PROFILE(SMBwriteX);
2093 return ERROR_DOS(ERRDOS,ERRbadaccess);
2096 #endif /* LARGE_SMB_OFF_T */
2099 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2100 END_PROFILE(SMBwriteX);
2101 return ERROR_DOS(ERRDOS,ERRlock);
2104 /* X/Open SMB protocol says that, unlike SMBwrite
2105 if the length is zero then NO truncation is
2106 done, just a write of zero. To truncate a file,
2111 nwritten = write_file(fsp,data,startpos,numtowrite);
2113 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2114 END_PROFILE(SMBwriteX);
2115 return(UNIXERROR(ERRDOS,ERRnoaccess));
2118 set_message(outbuf,6,0,True);
2120 SSVAL(outbuf,smb_vwv2,nwritten);
2122 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2124 if (nwritten < (ssize_t)numtowrite) {
2125 SCVAL(outbuf,smb_rcls,ERRHRD);
2126 SSVAL(outbuf,smb_err,ERRdiskfull);
2129 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2130 fsp->fnum, (int)numtowrite, (int)nwritten));
2132 if (lp_syncalways(SNUM(conn)) || write_through)
2133 sync_file(conn,fsp);
2135 END_PROFILE(SMBwriteX);
2136 return chain_reply(inbuf,outbuf,length,bufsize);
2140 /****************************************************************************
2142 ****************************************************************************/
2144 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2150 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2151 START_PROFILE(SMBlseek);
2153 CHECK_FSP(fsp,conn);
2155 flush_write_cache(fsp, SEEK_FLUSH);
2157 mode = SVAL(inbuf,smb_vwv1) & 3;
2158 startpos = IVALS(inbuf,smb_vwv2);
2161 case 0: umode = SEEK_SET; break;
2162 case 1: umode = SEEK_CUR; break;
2163 case 2: umode = SEEK_END; break;
2165 umode = SEEK_SET; break;
2168 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2170 * Check for the special case where a seek before the start
2171 * of the file sets the offset to zero. Added in the CIFS spec,
2175 if(errno == EINVAL) {
2176 SMB_OFF_T current_pos = startpos;
2178 if(umode == SEEK_CUR) {
2180 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2181 END_PROFILE(SMBlseek);
2182 return(UNIXERROR(ERRDOS,ERRnoaccess));
2185 current_pos += startpos;
2187 } else if (umode == SEEK_END) {
2189 SMB_STRUCT_STAT sbuf;
2191 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2192 END_PROFILE(SMBlseek);
2193 return(UNIXERROR(ERRDOS,ERRnoaccess));
2196 current_pos += sbuf.st_size;
2200 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2204 END_PROFILE(SMBlseek);
2205 return(UNIXERROR(ERRDOS,ERRnoaccess));
2211 outsize = set_message(outbuf,2,0,True);
2212 SIVAL(outbuf,smb_vwv0,res);
2214 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2215 fsp->fnum, (double)startpos, (double)res, mode));
2217 END_PROFILE(SMBlseek);
2221 /****************************************************************************
2223 ****************************************************************************/
2225 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2227 int outsize = set_message(outbuf,0,0,True);
2228 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2229 START_PROFILE(SMBflush);
2231 CHECK_FSP(fsp,conn);
2234 file_sync_all(conn);
2236 sync_file(conn,fsp);
2239 DEBUG(3,("flush\n"));
2240 END_PROFILE(SMBflush);
2245 /****************************************************************************
2247 ****************************************************************************/
2248 int reply_exit(connection_struct *conn,
2249 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2252 START_PROFILE(SMBexit);
2253 outsize = set_message(outbuf,0,0,True);
2255 DEBUG(3,("exit\n"));
2257 END_PROFILE(SMBexit);
2262 /****************************************************************************
2263 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2264 ****************************************************************************/
2265 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2270 int32 eclass = 0, err = 0;
2271 files_struct *fsp = NULL;
2272 START_PROFILE(SMBclose);
2274 outsize = set_message(outbuf,0,0,True);
2276 /* If it's an IPC, pass off to the pipe handler. */
2278 END_PROFILE(SMBclose);
2279 return reply_pipe_close(conn, inbuf,outbuf);
2282 fsp = file_fsp(inbuf,smb_vwv0);
2285 * We can only use CHECK_FSP if we know it's not a directory.
2288 if(!fsp || (fsp->conn != conn)) {
2289 END_PROFILE(SMBclose);
2290 return ERROR_DOS(ERRDOS,ERRbadfid);
2293 if(fsp->is_directory) {
2295 * Special case - close NT SMB directory handle.
2297 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2298 close_file(fsp,True);
2301 * Close ordinary file.
2306 /* Save the name for time set in close. */
2307 pstrcpy( file_name, fsp->fsp_name);
2309 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2311 conn->num_files_open));
2314 * close_file() returns the unix errno if an error
2315 * was detected on close - normally this is due to
2316 * a disk full error. If not then it was probably an I/O error.
2319 if((close_err = close_file(fsp,True)) != 0) {
2321 END_PROFILE(SMBclose);
2322 return (UNIXERROR(ERRHRD,ERRgeneral));
2326 * Now take care of any time sent in the close.
2329 mtime = make_unix_date3(inbuf+smb_vwv1);
2331 /* try and set the date */
2332 set_filetime(conn, file_name, mtime);
2336 /* We have a cached error */
2338 END_PROFILE(SMBclose);
2339 return ERROR_DOS(eclass,err);
2342 END_PROFILE(SMBclose);
2347 /****************************************************************************
2348 reply to a writeclose (Core+ protocol)
2349 ****************************************************************************/
2351 int reply_writeclose(connection_struct *conn,
2352 char *inbuf,char *outbuf, int size, int dum_buffsize)
2355 ssize_t nwritten = -1;
2361 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2362 START_PROFILE(SMBwriteclose);
2364 CHECK_FSP(fsp,conn);
2367 numtowrite = SVAL(inbuf,smb_vwv1);
2368 startpos = IVAL(inbuf,smb_vwv2);
2369 mtime = make_unix_date3(inbuf+smb_vwv4);
2370 data = smb_buf(inbuf) + 1;
2372 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2373 END_PROFILE(SMBwriteclose);
2374 return ERROR_DOS(ERRDOS,ERRlock);
2377 nwritten = write_file(fsp,data,startpos,numtowrite);
2379 set_filetime(conn, fsp->fsp_name,mtime);
2381 close_err = close_file(fsp,True);
2383 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2384 fsp->fnum, (int)numtowrite, (int)nwritten,
2385 conn->num_files_open));
2387 if (nwritten <= 0) {
2388 END_PROFILE(SMBwriteclose);
2389 return(UNIXERROR(ERRDOS,ERRnoaccess));
2392 if(close_err != 0) {
2394 END_PROFILE(SMBwriteclose);
2395 return(UNIXERROR(ERRHRD,ERRgeneral));
2398 outsize = set_message(outbuf,1,0,True);
2400 SSVAL(outbuf,smb_vwv0,nwritten);
2401 END_PROFILE(SMBwriteclose);
2406 /****************************************************************************
2408 ****************************************************************************/
2409 int reply_lock(connection_struct *conn,
2410 char *inbuf,char *outbuf, int length, int dum_buffsize)
2412 int outsize = set_message(outbuf,0,0,True);
2413 SMB_BIG_UINT count,offset;
2415 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2416 START_PROFILE(SMBlock);
2418 CHECK_FSP(fsp,conn);
2420 release_level_2_oplocks_on_change(fsp);
2422 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2423 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2425 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2426 fsp->fd, fsp->fnum, (double)offset, (double)count));
2428 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2429 if (NT_STATUS_V(status)) {
2430 if (lp_blocking_locks(SNUM(conn))) {
2432 * A blocking lock was requested. Package up
2433 * this smb into a queued request and push it
2434 * onto the blocking lock queue.
2436 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2437 END_PROFILE(SMBlock);
2441 END_PROFILE(SMBlock);
2442 return ERROR_NT(status);
2445 END_PROFILE(SMBlock);
2450 /****************************************************************************
2452 ****************************************************************************/
2453 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2456 int outsize = set_message(outbuf,0,0,True);
2457 SMB_BIG_UINT count,offset;
2459 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2460 START_PROFILE(SMBunlock);
2462 CHECK_FSP(fsp,conn);
2464 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2465 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2467 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2468 if (NT_STATUS_V(status)) {
2469 END_PROFILE(SMBunlock);
2470 return ERROR_NT(status);
2473 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2474 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2476 END_PROFILE(SMBunlock);
2481 /****************************************************************************
2483 ****************************************************************************/
2484 int reply_tdis(connection_struct *conn,
2485 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2487 int outsize = set_message(outbuf,0,0,True);
2489 START_PROFILE(SMBtdis);
2491 vuid = SVAL(inbuf,smb_uid);
2494 DEBUG(4,("Invalid connection in tdis\n"));
2495 END_PROFILE(SMBtdis);
2496 return ERROR_DOS(ERRSRV,ERRinvnid);
2501 close_cnum(conn,vuid);
2503 END_PROFILE(SMBtdis);
2509 /****************************************************************************
2511 ****************************************************************************/
2512 int reply_echo(connection_struct *conn,
2513 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2515 int smb_reverb = SVAL(inbuf,smb_vwv0);
2517 unsigned int data_len = smb_buflen(inbuf);
2518 int outsize = set_message(outbuf,1,data_len,True);
2519 START_PROFILE(SMBecho);
2521 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2523 /* copy any incoming data back out */
2525 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2527 if (smb_reverb > 100) {
2528 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2532 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2533 SSVAL(outbuf,smb_vwv0,seq_num);
2535 smb_setlen(outbuf,outsize - 4);
2537 if (!send_smb(smbd_server_fd(),outbuf))
2538 exit_server("reply_echo: send_smb failed.");
2541 DEBUG(3,("echo %d times\n", smb_reverb));
2545 END_PROFILE(SMBecho);
2550 /****************************************************************************
2551 reply to a printopen
2552 ****************************************************************************/
2553 int reply_printopen(connection_struct *conn,
2554 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2558 START_PROFILE(SMBsplopen);
2560 if (!CAN_PRINT(conn)) {
2561 END_PROFILE(SMBsplopen);
2562 return ERROR_DOS(ERRDOS,ERRnoaccess);
2565 /* Open for exclusive use, write only. */
2566 fsp = print_fsp_open(conn, NULL);
2569 END_PROFILE(SMBsplopen);
2570 return(UNIXERROR(ERRDOS,ERRnoaccess));
2573 outsize = set_message(outbuf,1,0,True);
2574 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2576 DEBUG(3,("openprint fd=%d fnum=%d\n",
2577 fsp->fd, fsp->fnum));
2579 END_PROFILE(SMBsplopen);
2584 /****************************************************************************
2585 reply to a printclose
2586 ****************************************************************************/
2587 int reply_printclose(connection_struct *conn,
2588 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2590 int outsize = set_message(outbuf,0,0,True);
2591 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2593 START_PROFILE(SMBsplclose);
2595 CHECK_FSP(fsp,conn);
2597 if (!CAN_PRINT(conn)) {
2598 END_PROFILE(SMBsplclose);
2599 return ERROR_DOS(ERRDOS,ERRnoaccess);
2602 DEBUG(3,("printclose fd=%d fnum=%d\n",
2603 fsp->fd,fsp->fnum));
2605 close_err = close_file(fsp,True);
2607 if(close_err != 0) {
2609 END_PROFILE(SMBsplclose);
2610 return(UNIXERROR(ERRHRD,ERRgeneral));
2613 END_PROFILE(SMBsplclose);
2618 /****************************************************************************
2619 reply to a printqueue
2620 ****************************************************************************/
2621 int reply_printqueue(connection_struct *conn,
2622 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2624 int outsize = set_message(outbuf,2,3,True);
2625 int max_count = SVAL(inbuf,smb_vwv0);
2626 int start_index = SVAL(inbuf,smb_vwv1);
2627 START_PROFILE(SMBsplretq);
2629 /* we used to allow the client to get the cnum wrong, but that
2630 is really quite gross and only worked when there was only
2631 one printer - I think we should now only accept it if they
2632 get it right (tridge) */
2633 if (!CAN_PRINT(conn)) {
2634 END_PROFILE(SMBsplretq);
2635 return ERROR_DOS(ERRDOS,ERRnoaccess);
2638 SSVAL(outbuf,smb_vwv0,0);
2639 SSVAL(outbuf,smb_vwv1,0);
2640 SCVAL(smb_buf(outbuf),0,1);
2641 SSVAL(smb_buf(outbuf),1,0);
2643 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2644 start_index, max_count));
2647 print_queue_struct *queue = NULL;
2648 print_status_struct status;
2649 char *p = smb_buf(outbuf) + 3;
2650 int count = print_queue_status(SNUM(conn), &queue, &status);
2651 int num_to_get = ABS(max_count);
2652 int first = (max_count>0?start_index:start_index+max_count+1);
2658 num_to_get = MIN(num_to_get,count-first);
2661 for (i=first;i<first+num_to_get;i++) {
2662 put_dos_date2(p,0,queue[i].time);
2663 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2664 SSVAL(p,5, queue[i].job);
2665 SIVAL(p,7,queue[i].size);
2667 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2672 outsize = set_message(outbuf,2,28*count+3,False);
2673 SSVAL(outbuf,smb_vwv0,count);
2674 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2675 SCVAL(smb_buf(outbuf),0,1);
2676 SSVAL(smb_buf(outbuf),1,28*count);
2681 DEBUG(3,("%d entries returned in queue\n",count));
2684 END_PROFILE(SMBsplretq);
2689 /****************************************************************************
2690 reply to a printwrite
2691 ****************************************************************************/
2692 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2695 int outsize = set_message(outbuf,0,0,True);
2697 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2698 START_PROFILE(SMBsplwr);
2700 if (!CAN_PRINT(conn)) {
2701 END_PROFILE(SMBsplwr);
2702 return ERROR_DOS(ERRDOS,ERRnoaccess);
2705 CHECK_FSP(fsp,conn);
2708 numtowrite = SVAL(smb_buf(inbuf),1);
2709 data = smb_buf(inbuf) + 3;
2711 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2712 END_PROFILE(SMBsplwr);
2713 return(UNIXERROR(ERRDOS,ERRnoaccess));
2716 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2718 END_PROFILE(SMBsplwr);
2723 /****************************************************************************
2724 The guts of the mkdir command, split out so it may be called by the NT SMB
2726 ****************************************************************************/
2727 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2729 BOOL bad_path = False;
2730 SMB_STRUCT_STAT sbuf;
2733 unix_convert(directory,conn,0,&bad_path,&sbuf);
2735 if (check_name(directory, conn))
2736 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2739 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2740 if (!NT_STATUS_IS_OK(nterr))
2742 return map_nt_error_from_unix(errno);
2745 return NT_STATUS_OK;
2748 /****************************************************************************
2750 ****************************************************************************/
2752 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2757 START_PROFILE(SMBmkdir);
2759 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2761 status = mkdir_internal(conn, directory);
2762 if (!NT_STATUS_IS_OK(status))
2763 return ERROR_NT(status);
2765 outsize = set_message(outbuf,0,0,True);
2767 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2769 END_PROFILE(SMBmkdir);
2773 /****************************************************************************
2774 Static function used by reply_rmdir to delete an entire directory
2775 tree recursively. Return False on ok, True on fail.
2776 ****************************************************************************/
2778 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2782 void *dirptr = OpenDir(conn, directory, False);
2787 while((dname = ReadDirName(dirptr))) {
2791 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2794 /* Construct the full name. */
2795 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2801 pstrcpy(fullname, directory);
2802 pstrcat(fullname, "/");
2803 pstrcat(fullname, dname);
2805 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2810 if(st.st_mode & S_IFDIR) {
2811 if(recursive_rmdir(conn, fullname)!=0) {
2815 if(vfs_rmdir(conn,fullname) != 0) {
2819 } else if(vfs_unlink(conn,fullname) != 0) {
2828 /****************************************************************************
2829 The internals of the rmdir code - called elsewhere.
2830 ****************************************************************************/
2832 BOOL rmdir_internals(connection_struct *conn, char *directory)
2836 ok = (vfs_rmdir(conn,directory) == 0);
2837 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2839 * Check to see if the only thing in this directory are
2840 * vetoed files/directories. If so then delete them and
2841 * retry. If we fail to delete any of them (and we *don't*
2842 * do a recursive delete) then fail the rmdir.
2844 BOOL all_veto_files = True;
2846 void *dirptr = OpenDir(conn, directory, False);
2848 if(dirptr != NULL) {
2849 int dirpos = TellDir(dirptr);
2850 while ((dname = ReadDirName(dirptr))) {
2851 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2853 if(!IS_VETO_PATH(conn, dname)) {
2854 all_veto_files = False;
2859 if(all_veto_files) {
2860 SeekDir(dirptr,dirpos);
2861 while ((dname = ReadDirName(dirptr))) {
2865 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2868 /* Construct the full name. */
2869 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2874 pstrcpy(fullname, directory);
2875 pstrcat(fullname, "/");
2876 pstrcat(fullname, dname);
2878 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2880 if(st.st_mode & S_IFDIR) {
2881 if(lp_recursive_veto_delete(SNUM(conn))) {
2882 if(recursive_rmdir(conn, fullname) != 0)
2885 if(vfs_rmdir(conn,fullname) != 0)
2887 } else if(vfs_unlink(conn,fullname) != 0)
2891 /* Retry the rmdir */
2892 ok = (vfs_rmdir(conn,directory) == 0);
2902 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
2907 /****************************************************************************
2909 ****************************************************************************/
2911 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2916 BOOL bad_path = False;
2917 SMB_STRUCT_STAT sbuf;
2918 START_PROFILE(SMBrmdir);
2920 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2922 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
2924 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
2926 if (check_name(directory,conn))
2928 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2929 ok = rmdir_internals(conn, directory);
2934 set_bad_path_error(errno, bad_path);
2935 END_PROFILE(SMBrmdir);
2936 return(UNIXERROR(ERRDOS,ERRbadpath));
2939 outsize = set_message(outbuf,0,0,True);
2941 DEBUG( 3, ( "rmdir %s\n", directory ) );
2943 END_PROFILE(SMBrmdir);
2948 /*******************************************************************
2949 resolve wildcards in a filename rename
2950 ********************************************************************/
2951 static BOOL resolve_wildcards(char *name1,char *name2)
2953 fstring root1,root2;
2957 name1 = strrchr_m(name1,'/');
2958 name2 = strrchr_m(name2,'/');
2960 if (!name1 || !name2) return(False);
2962 fstrcpy(root1,name1);
2963 fstrcpy(root2,name2);
2964 p = strrchr_m(root1,'.');
2971 p = strrchr_m(root2,'.');
3003 pstrcpy(name2,root2);
3006 pstrcat(name2,ext2);
3012 /****************************************************************************
3013 The guts of the rename command, split out so it may be called by the NT SMB
3015 ****************************************************************************/
3017 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3021 pstring newname_last_component;
3024 BOOL bad_path1 = False;
3025 BOOL bad_path2 = False;
3027 NTSTATUS error = NT_STATUS_OK;
3029 SMB_STRUCT_STAT sbuf1, sbuf2;
3031 *directory = *mask = 0;
3033 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3034 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3037 * Split the old name into directory and last component
3038 * strings. Note that unix_convert may have stripped off a
3039 * leading ./ from both name and newname if the rename is
3040 * at the root of the share. We need to make sure either both
3041 * name and newname contain a / character or neither of them do
3042 * as this is checked in resolve_wildcards().
3045 p = strrchr_m(name,'/');
3047 pstrcpy(directory,".");
3051 pstrcpy(directory,name);
3053 *p = '/'; /* Replace needed for exceptional test below. */
3057 * We should only check the mangled cache
3058 * here if unix_convert failed. This means
3059 * that the path in 'mask' doesn't exist
3060 * on the file system and so we need to look
3061 * for a possible mangle. This patch from
3062 * Tine Smukavec <valentin.smukavec@hermes.si>.
3065 if (!rc && mangle_is_mangled(mask))
3066 mangle_check_cache( mask );
3068 has_wild = ms_has_wild(mask);
3072 * No wildcards - just process the one file.
3074 BOOL is_short_name = mangle_is_8_3(name, True);
3076 /* Add a terminating '/' to the directory name. */
3077 pstrcat(directory,"/");
3078 pstrcat(directory,mask);
3080 /* Ensure newname contains a '/' also */
3081 if(strrchr_m(newname,'/') == 0) {
3084 pstrcpy(tmpstr, "./");
3085 pstrcat(tmpstr, newname);
3086 pstrcpy(newname, tmpstr);
3089 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3090 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3091 case_sensitive, case_preserve, short_case_preserve, directory,
3092 newname, newname_last_component, is_short_name));
3095 * Check for special case with case preserving and not
3096 * case sensitive, if directory and newname are identical,
3097 * and the old last component differs from the original
3098 * last component only by case, then we should allow
3099 * the rename (user is trying to change the case of the
3102 if((case_sensitive == False) &&
3103 (((case_preserve == True) &&
3104 (is_short_name == False)) ||
3105 ((short_case_preserve == True) &&
3106 (is_short_name == True))) &&
3107 strcsequal(directory, newname)) {
3108 pstring newname_modified_last_component;
3111 * Get the last component of the modified name.
3112 * Note that we guarantee that newname contains a '/'
3115 p = strrchr_m(newname,'/');
3116 pstrcpy(newname_modified_last_component,p+1);
3118 if(strcsequal(newname_modified_last_component,
3119 newname_last_component) == False) {
3121 * Replace the modified last component with
3124 pstrcpy(p+1, newname_last_component);
3128 resolve_wildcards(directory,newname);
3131 * The source object must exist.
3134 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3135 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3136 directory,newname));
3138 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3140 * Must return different errors depending on whether the parent
3141 * directory existed or not.
3144 p = strrchr_m(directory, '/');
3146 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3148 if (vfs_object_exist(conn, directory, NULL))
3149 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3150 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3152 error = map_nt_error_from_unix(errno);
3153 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3154 nt_errstr(error), directory,newname));
3159 error = can_rename(directory,conn,&sbuf1);
3161 if (!NT_STATUS_IS_OK(error)) {
3162 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3163 nt_errstr(error), directory,newname));
3168 * If the src and dest names are identical - including case,
3169 * don't do the rename, just return success.
3172 if (strcsequal(directory, newname)) {
3173 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3174 return NT_STATUS_OK;
3177 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3178 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3179 directory,newname));
3180 return NT_STATUS_OBJECT_NAME_COLLISION;
3183 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3184 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3185 directory,newname));
3186 return NT_STATUS_OK;
3189 if (errno == ENOTDIR || errno == EISDIR)
3190 error = NT_STATUS_OBJECT_NAME_COLLISION;
3192 error = map_nt_error_from_unix(errno);
3194 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3195 nt_errstr(error), directory,newname));
3200 * Wildcards - process each file that matches.
3202 void *dirptr = NULL;
3206 if (check_name(directory,conn))
3207 dirptr = OpenDir(conn, directory, True);
3210 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3212 if (strequal(mask,"????????.???"))
3215 while ((dname = ReadDirName(dirptr))) {
3218 pstrcpy(fname,dname);
3220 if(!mask_match(fname, mask, case_sensitive))
3223 error = NT_STATUS_ACCESS_DENIED;
3224 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3225 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3226 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3227 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3230 error = can_rename(fname,conn,&sbuf1);
3231 if (!NT_STATUS_IS_OK(error)) {
3232 DEBUG(6,("rename %s refused\n", fname));
3235 pstrcpy(destname,newname);
3237 if (!resolve_wildcards(fname,destname)) {
3238 DEBUG(6,("resolve_wildcards %s %s failed\n",
3243 if (!replace_if_exists &&
3244 vfs_file_exist(conn,destname, NULL)) {
3245 DEBUG(6,("file_exist %s\n", destname));
3246 error = NT_STATUS_OBJECT_NAME_COLLISION;
3250 if (!conn->vfs_ops.rename(conn,fname,destname))
3252 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3258 if (count == 0 && NT_STATUS_IS_OK(error)) {
3259 error = map_nt_error_from_unix(errno);
3265 /****************************************************************************
3267 ****************************************************************************/
3269 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3278 START_PROFILE(SMBmv);
3280 p = smb_buf(inbuf) + 1;
3281 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3283 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3285 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3286 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3288 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3290 status = rename_internals(conn, name, newname, False);
3291 if (!NT_STATUS_IS_OK(status)) {
3292 return ERROR_NT(status);
3296 * Win2k needs a changenotify request response before it will
3297 * update after a rename..
3299 process_pending_change_notify_queue((time_t)0);
3300 outsize = set_message(outbuf,0,0,True);
3306 /*******************************************************************
3307 Copy a file as part of a reply_copy.
3308 ******************************************************************/
3310 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3311 int count,BOOL target_is_directory, int *err_ret)
3314 SMB_STRUCT_STAT src_sbuf, sbuf2;
3316 files_struct *fsp1,*fsp2;
3321 pstrcpy(dest,dest1);
3322 if (target_is_directory) {
3323 char *p = strrchr_m(src,'/');
3332 if (!vfs_file_exist(conn,src,&src_sbuf))
3335 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3336 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3341 if (!target_is_directory && count)
3342 ofun = FILE_EXISTS_OPEN;
3344 if (vfs_stat(conn,dest,&sbuf2) == -1)
3345 ZERO_STRUCTP(&sbuf2);
3347 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3348 ofun,src_sbuf.st_mode,0,&Access,&action);
3351 close_file(fsp1,False);
3355 if ((ofun&3) == 1) {
3356 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3357 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3359 * Stop the copy from occurring.
3362 src_sbuf.st_size = 0;
3366 if (src_sbuf.st_size)
3367 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3369 close_file(fsp1,False);
3371 /* Ensure the modtime is set correctly on the destination file. */
3372 fsp2->pending_modtime = src_sbuf.st_mtime;
3375 * As we are opening fsp1 read-only we only expect
3376 * an error on close on fsp2 if we are out of space.
3377 * Thus we don't look at the error return from the
3380 *err_ret = close_file(fsp2,False);
3382 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3385 /****************************************************************************
3386 reply to a file copy.
3387 ****************************************************************************/
3388 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3393 pstring mask,newname;
3396 int error = ERRnoaccess;
3400 int tid2 = SVAL(inbuf,smb_vwv0);
3401 int ofun = SVAL(inbuf,smb_vwv1);
3402 int flags = SVAL(inbuf,smb_vwv2);
3403 BOOL target_is_directory=False;
3404 BOOL bad_path1 = False;
3405 BOOL bad_path2 = False;
3407 SMB_STRUCT_STAT sbuf1, sbuf2;
3408 START_PROFILE(SMBcopy);
3410 *directory = *mask = 0;
3413 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3414 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3416 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3418 if (tid2 != conn->cnum) {
3419 /* can't currently handle inter share copies XXXX */
3420 DEBUG(3,("Rejecting inter-share copy\n"));
3421 END_PROFILE(SMBcopy);
3422 return ERROR_DOS(ERRSRV,ERRinvdevice);
3425 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3426 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3428 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3429 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3431 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3433 if ((flags&1) && target_is_directory) {
3434 END_PROFILE(SMBcopy);
3435 return ERROR_DOS(ERRDOS,ERRbadfile);
3438 if ((flags&2) && !target_is_directory) {
3439 END_PROFILE(SMBcopy);
3440 return ERROR_DOS(ERRDOS,ERRbadpath);
3443 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3444 /* wants a tree copy! XXXX */
3445 DEBUG(3,("Rejecting tree copy\n"));
3446 END_PROFILE(SMBcopy);
3447 return ERROR_DOS(ERRSRV,ERRerror);
3450 p = strrchr_m(name,'/');
3452 pstrcpy(directory,"./");
3456 pstrcpy(directory,name);
3461 * We should only check the mangled cache
3462 * here if unix_convert failed. This means
3463 * that the path in 'mask' doesn't exist
3464 * on the file system and so we need to look
3465 * for a possible mangle. This patch from
3466 * Tine Smukavec <valentin.smukavec@hermes.si>.
3469 if (!rc && mangle_is_mangled(mask))
3470 mangle_check_cache( mask );
3472 has_wild = ms_has_wild(mask);
3475 pstrcat(directory,"/");
3476 pstrcat(directory,mask);
3477 if (resolve_wildcards(directory,newname) &&
3478 copy_file(directory,newname,conn,ofun,
3479 count,target_is_directory,&err)) count++;
3482 END_PROFILE(SMBcopy);
3483 return(UNIXERROR(ERRHRD,ERRgeneral));
3485 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3487 void *dirptr = NULL;
3491 if (check_name(directory,conn))
3492 dirptr = OpenDir(conn, directory, True);
3497 if (strequal(mask,"????????.???"))
3500 while ((dname = ReadDirName(dirptr))) {
3502 pstrcpy(fname,dname);
3504 if(!mask_match(fname, mask, case_sensitive))
3507 error = ERRnoaccess;
3508 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3509 pstrcpy(destname,newname);
3510 if (resolve_wildcards(fname,destname) &&
3511 copy_file(fname,destname,conn,ofun,
3512 count,target_is_directory,&err)) count++;
3513 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3521 /* Error on close... */
3523 END_PROFILE(SMBcopy);
3524 return(UNIXERROR(ERRHRD,ERRgeneral));
3528 END_PROFILE(SMBcopy);
3529 return ERROR_DOS(ERRDOS,error);
3532 if((errno == ENOENT) && (bad_path1 || bad_path2))
3534 unix_ERR_class = ERRDOS;
3535 unix_ERR_code = ERRbadpath;
3537 END_PROFILE(SMBcopy);
3538 return(UNIXERROR(ERRDOS,error));
3542 outsize = set_message(outbuf,1,0,True);
3543 SSVAL(outbuf,smb_vwv0,count);
3545 END_PROFILE(SMBcopy);
3549 /****************************************************************************
3551 ****************************************************************************/
3552 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3558 START_PROFILE(pathworks_setdir);
3561 if (!CAN_SETDIR(snum)) {
3562 END_PROFILE(pathworks_setdir);
3563 return ERROR_DOS(ERRDOS,ERRnoaccess);
3566 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3568 if (strlen(newdir) == 0) {
3571 ok = vfs_directory_exist(conn,newdir,NULL);
3573 string_set(&conn->connectpath,newdir);
3578 END_PROFILE(pathworks_setdir);
3579 return ERROR_DOS(ERRDOS,ERRbadpath);
3582 outsize = set_message(outbuf,0,0,True);
3583 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3585 DEBUG(3,("setdir %s\n", newdir));
3587 END_PROFILE(pathworks_setdir);
3591 /****************************************************************************
3592 Get a lock pid, dealing with large count requests.
3593 ****************************************************************************/
3595 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3597 if(!large_file_format)
3598 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3600 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3603 /****************************************************************************
3604 Get a lock count, dealing with large count requests.
3605 ****************************************************************************/
3607 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3609 SMB_BIG_UINT count = 0;
3611 if(!large_file_format) {
3612 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3615 #if defined(HAVE_LONGLONG)
3616 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3617 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3618 #else /* HAVE_LONGLONG */
3621 * NT4.x seems to be broken in that it sends large file (64 bit)
3622 * lockingX calls even if the CAP_LARGE_FILES was *not*
3623 * negotiated. For boxes without large unsigned ints truncate the
3624 * lock count by dropping the top 32 bits.
3627 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3628 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3629 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3630 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3631 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3634 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3635 #endif /* HAVE_LONGLONG */
3641 #if !defined(HAVE_LONGLONG)
3642 /****************************************************************************
3643 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3644 ****************************************************************************/
3645 static uint32 map_lock_offset(uint32 high, uint32 low)
3649 uint32 highcopy = high;
3652 * Try and find out how many significant bits there are in high.
3655 for(i = 0; highcopy; i++)
3659 * We use 31 bits not 32 here as POSIX
3660 * lock offsets may not be negative.
3663 mask = (~0) << (31 - i);
3666 return 0; /* Fail. */
3672 #endif /* !defined(HAVE_LONGLONG) */
3674 /****************************************************************************
3675 Get a lock offset, dealing with large offset requests.
3676 ****************************************************************************/
3678 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3680 SMB_BIG_UINT offset = 0;
3684 if(!large_file_format) {
3685 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3688 #if defined(HAVE_LONGLONG)
3689 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3690 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3691 #else /* HAVE_LONGLONG */
3694 * NT4.x seems to be broken in that it sends large file (64 bit)
3695 * lockingX calls even if the CAP_LARGE_FILES was *not*
3696 * negotiated. For boxes without large unsigned ints mangle the
3697 * lock offset by mapping the top 32 bits onto the lower 32.
3700 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3701 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3702 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3705 if((new_low = map_lock_offset(high, low)) == 0) {
3707 return (SMB_BIG_UINT)-1;
3710 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3711 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3712 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3713 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3716 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3717 #endif /* HAVE_LONGLONG */
3723 /****************************************************************************
3724 reply to a lockingX request
3725 ****************************************************************************/
3727 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3729 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3730 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3731 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3732 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3733 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3734 SMB_BIG_UINT count = 0, offset = 0;
3736 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3739 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3743 START_PROFILE(SMBlockingX);
3745 CHECK_FSP(fsp,conn);
3747 data = smb_buf(inbuf);
3749 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3750 /* we don't support these - and CANCEL_LOCK makes w2k
3751 and XP reboot so I don't really want to be
3752 compatible! (tridge) */
3753 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3756 /* Check if this is an oplock break on a file
3757 we have granted an oplock on.
3759 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3760 /* Client can insist on breaking to none. */
3761 BOOL break_to_none = (oplocklevel == 0);
3763 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3764 (unsigned int)oplocklevel, fsp->fnum ));
3767 * Make sure we have granted an exclusive or batch oplock on this file.
3770 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3771 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3772 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3774 /* if this is a pure oplock break request then don't send a reply */
3775 if (num_locks == 0 && num_ulocks == 0) {
3776 END_PROFILE(SMBlockingX);
3779 END_PROFILE(SMBlockingX);
3780 return ERROR_DOS(ERRDOS,ERRlock);
3784 if (remove_oplock(fsp, break_to_none) == False) {
3785 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3789 /* if this is a pure oplock break request then don't send a reply */
3790 if (num_locks == 0 && num_ulocks == 0) {
3791 /* Sanity check - ensure a pure oplock break is not a
3793 if(CVAL(inbuf,smb_vwv0) != 0xff)
3794 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3795 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3796 END_PROFILE(SMBlockingX);
3802 * We do this check *after* we have checked this is not a oplock break
3803 * response message. JRA.
3806 release_level_2_oplocks_on_change(fsp);
3808 /* Data now points at the beginning of the list
3809 of smb_unlkrng structs */
3810 for(i = 0; i < (int)num_ulocks; i++) {
3811 lock_pid = get_lock_pid( data, i, large_file_format);
3812 count = get_lock_count( data, i, large_file_format);
3813 offset = get_lock_offset( data, i, large_file_format, &err);
3816 * There is no error code marked "stupid client bug".... :-).
3819 END_PROFILE(SMBlockingX);
3820 return ERROR_DOS(ERRDOS,ERRnoaccess);
3823 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3824 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3826 status = do_unlock(fsp,conn,lock_pid,count,offset);
3827 if (NT_STATUS_V(status)) {
3828 END_PROFILE(SMBlockingX);
3829 return ERROR_NT(status);
3833 /* Setup the timeout in seconds. */
3835 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3837 /* Now do any requested locks */
3838 data += ((large_file_format ? 20 : 10)*num_ulocks);
3840 /* Data now points at the beginning of the list
3841 of smb_lkrng structs */
3843 for(i = 0; i < (int)num_locks; i++) {
3844 lock_pid = get_lock_pid( data, i, large_file_format);
3845 count = get_lock_count( data, i, large_file_format);
3846 offset = get_lock_offset( data, i, large_file_format, &err);
3849 * There is no error code marked "stupid client bug".... :-).
3852 END_PROFILE(SMBlockingX);
3853 return ERROR_DOS(ERRDOS,ERRnoaccess);
3856 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3857 (double)offset, (double)count, (unsigned int)lock_pid,
3858 fsp->fsp_name, (int)lock_timeout ));
3860 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3861 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3862 if (NT_STATUS_V(status)) {
3863 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3865 * A blocking lock was requested. Package up
3866 * this smb into a queued request and push it
3867 * onto the blocking lock queue.
3869 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3870 END_PROFILE(SMBlockingX);
3878 /* If any of the above locks failed, then we must unlock
3879 all of the previous locks (X/Open spec). */
3880 if (i != num_locks && num_locks != 0) {
3882 * Ensure we don't do a remove on the lock that just failed,
3883 * as under POSIX rules, if we have a lock already there, we
3884 * will delete it (and we shouldn't) .....
3886 for(i--; i >= 0; i--) {
3887 lock_pid = get_lock_pid( data, i, large_file_format);
3888 count = get_lock_count( data, i, large_file_format);
3889 offset = get_lock_offset( data, i, large_file_format, &err);
3892 * There is no error code marked "stupid client bug".... :-).
3895 END_PROFILE(SMBlockingX);
3896 return ERROR_DOS(ERRDOS,ERRnoaccess);
3899 do_unlock(fsp,conn,lock_pid,count,offset);
3901 END_PROFILE(SMBlockingX);
3902 return ERROR_NT(status);
3905 set_message(outbuf,2,0,True);
3907 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3908 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3910 END_PROFILE(SMBlockingX);
3911 return chain_reply(inbuf,outbuf,length,bufsize);
3914 /****************************************************************************
3915 Reply to a SMBreadbmpx (read block multiplex) request.
3916 ****************************************************************************/
3918 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3929 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3930 START_PROFILE(SMBreadBmpx);
3932 /* this function doesn't seem to work - disable by default */
3933 if (!lp_readbmpx()) {
3934 END_PROFILE(SMBreadBmpx);
3935 return ERROR_DOS(ERRSRV,ERRuseSTD);
3938 outsize = set_message(outbuf,8,0,True);
3940 CHECK_FSP(fsp,conn);
3943 startpos = IVAL(inbuf,smb_vwv1);
3944 maxcount = SVAL(inbuf,smb_vwv3);
3946 data = smb_buf(outbuf);
3947 pad = ((long)data)%4;
3952 max_per_packet = bufsize-(outsize+pad);
3956 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
3957 END_PROFILE(SMBreadBmpx);
3958 return ERROR_DOS(ERRDOS,ERRlock);
3962 size_t N = MIN(max_per_packet,tcount-total_read);
3964 nread = read_file(fsp,data,startpos,N);
3969 if (nread < (ssize_t)N)
3970 tcount = total_read + nread;
3972 set_message(outbuf,8,nread,False);
3973 SIVAL(outbuf,smb_vwv0,startpos);
3974 SSVAL(outbuf,smb_vwv2,tcount);
3975 SSVAL(outbuf,smb_vwv6,nread);
3976 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3978 if (!send_smb(smbd_server_fd(),outbuf))
3979 exit_server("reply_readbmpx: send_smb failed.");
3981 total_read += nread;
3983 } while (total_read < (ssize_t)tcount);
3985 END_PROFILE(SMBreadBmpx);
3989 /****************************************************************************
3990 Reply to a SMBsetattrE.
3991 ****************************************************************************/
3993 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3995 struct utimbuf unix_times;
3997 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3998 START_PROFILE(SMBsetattrE);
4000 outsize = set_message(outbuf,0,0,True);
4002 if(!fsp || (fsp->conn != conn)) {
4003 END_PROFILE(SMBgetattrE);
4004 return ERROR_DOS(ERRDOS,ERRbadfid);
4008 * Convert the DOS times into unix times. Ignore create
4009 * time as UNIX can't set this.
4012 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4013 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4016 * Patch from Ray Frush <frush@engr.colostate.edu>
4017 * Sometimes times are sent as zero - ignore them.
4020 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4021 /* Ignore request */
4022 if( DEBUGLVL( 3 ) ) {
4023 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4024 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4026 END_PROFILE(SMBsetattrE);
4028 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4029 /* set modify time = to access time if modify time was 0 */
4030 unix_times.modtime = unix_times.actime;
4033 /* Set the date on this file */
4034 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4035 END_PROFILE(SMBsetattrE);
4036 return ERROR_DOS(ERRDOS,ERRnoaccess);
4039 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4040 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4042 END_PROFILE(SMBsetattrE);
4047 /* Back from the dead for OS/2..... JRA. */
4049 /****************************************************************************
4050 Reply to a SMBwritebmpx (write block multiplex primary) request.
4051 ****************************************************************************/
4053 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4056 ssize_t nwritten = -1;
4063 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4064 START_PROFILE(SMBwriteBmpx);
4066 CHECK_FSP(fsp,conn);
4070 tcount = SVAL(inbuf,smb_vwv1);
4071 startpos = IVAL(inbuf,smb_vwv3);
4072 write_through = BITSETW(inbuf+smb_vwv7,0);
4073 numtowrite = SVAL(inbuf,smb_vwv10);
4074 smb_doff = SVAL(inbuf,smb_vwv11);
4076 data = smb_base(inbuf) + smb_doff;
4078 /* If this fails we need to send an SMBwriteC response,
4079 not an SMBwritebmpx - set this up now so we don't forget */
4080 SCVAL(outbuf,smb_com,SMBwritec);
4082 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4083 END_PROFILE(SMBwriteBmpx);
4084 return(ERROR_DOS(ERRDOS,ERRlock));
4087 nwritten = write_file(fsp,data,startpos,numtowrite);
4089 if(lp_syncalways(SNUM(conn)) || write_through)
4090 sync_file(conn,fsp);
4092 if(nwritten < (ssize_t)numtowrite) {
4093 END_PROFILE(SMBwriteBmpx);
4094 return(UNIXERROR(ERRHRD,ERRdiskfull));
4097 /* If the maximum to be written to this file
4098 is greater than what we just wrote then set
4099 up a secondary struct to be attached to this
4100 fd, we will use this to cache error messages etc. */
4102 if((ssize_t)tcount > nwritten) {
4103 write_bmpx_struct *wbms;
4104 if(fsp->wbmpx_ptr != NULL)
4105 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4107 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4109 DEBUG(0,("Out of memory in reply_readmpx\n"));
4110 END_PROFILE(SMBwriteBmpx);
4111 return(ERROR_DOS(ERRSRV,ERRnoresource));
4113 wbms->wr_mode = write_through;
4114 wbms->wr_discard = False; /* No errors yet */
4115 wbms->wr_total_written = nwritten;
4116 wbms->wr_errclass = 0;
4118 fsp->wbmpx_ptr = wbms;
4121 /* We are returning successfully, set the message type back to
4123 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4125 outsize = set_message(outbuf,1,0,True);
4127 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4129 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4130 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4132 if (write_through && tcount==nwritten) {
4133 /* We need to send both a primary and a secondary response */
4134 smb_setlen(outbuf,outsize - 4);
4135 if (!send_smb(smbd_server_fd(),outbuf))
4136 exit_server("reply_writebmpx: send_smb failed.");
4138 /* Now the secondary */
4139 outsize = set_message(outbuf,1,0,True);
4140 SCVAL(outbuf,smb_com,SMBwritec);
4141 SSVAL(outbuf,smb_vwv0,nwritten);
4144 END_PROFILE(SMBwriteBmpx);
4148 /****************************************************************************
4149 Reply to a SMBwritebs (write block multiplex secondary) request.
4150 ****************************************************************************/
4152 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4155 ssize_t nwritten = -1;
4162 write_bmpx_struct *wbms;
4163 BOOL send_response = False;
4164 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4165 START_PROFILE(SMBwriteBs);
4167 CHECK_FSP(fsp,conn);
4170 tcount = SVAL(inbuf,smb_vwv1);
4171 startpos = IVAL(inbuf,smb_vwv2);
4172 numtowrite = SVAL(inbuf,smb_vwv6);
4173 smb_doff = SVAL(inbuf,smb_vwv7);
4175 data = smb_base(inbuf) + smb_doff;
4177 /* We need to send an SMBwriteC response, not an SMBwritebs */
4178 SCVAL(outbuf,smb_com,SMBwritec);
4180 /* This fd should have an auxiliary struct attached,
4181 check that it does */
4182 wbms = fsp->wbmpx_ptr;
4184 END_PROFILE(SMBwriteBs);
4188 /* If write through is set we can return errors, else we must cache them */
4189 write_through = wbms->wr_mode;
4191 /* Check for an earlier error */
4192 if(wbms->wr_discard) {
4193 END_PROFILE(SMBwriteBs);
4194 return -1; /* Just discard the packet */
4197 nwritten = write_file(fsp,data,startpos,numtowrite);
4199 if(lp_syncalways(SNUM(conn)) || write_through)
4200 sync_file(conn,fsp);
4202 if (nwritten < (ssize_t)numtowrite) {
4204 /* We are returning an error - we can delete the aux struct */
4207 fsp->wbmpx_ptr = NULL;
4208 END_PROFILE(SMBwriteBs);
4209 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4211 END_PROFILE(SMBwriteBs);
4212 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4215 /* Increment the total written, if this matches tcount
4216 we can discard the auxiliary struct (hurrah !) and return a writeC */
4217 wbms->wr_total_written += nwritten;
4218 if(wbms->wr_total_written >= tcount) {
4219 if (write_through) {
4220 outsize = set_message(outbuf,1,0,True);
4221 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4222 send_response = True;
4226 fsp->wbmpx_ptr = NULL;
4230 END_PROFILE(SMBwriteBs);
4234 END_PROFILE(SMBwriteBs);
4238 /****************************************************************************
4239 Reply to a SMBgetattrE.
4240 ****************************************************************************/
4242 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4244 SMB_STRUCT_STAT sbuf;
4247 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4248 START_PROFILE(SMBgetattrE);
4250 outsize = set_message(outbuf,11,0,True);
4252 if(!fsp || (fsp->conn != conn)) {
4253 END_PROFILE(SMBgetattrE);
4254 return ERROR_DOS(ERRDOS,ERRbadfid);
4257 /* Do an fstat on this file */
4258 if(fsp_stat(fsp, &sbuf)) {
4259 END_PROFILE(SMBgetattrE);
4260 return(UNIXERROR(ERRDOS,ERRnoaccess));
4263 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4266 * Convert the times into dos times. Set create
4267 * date to be last modify date as UNIX doesn't save
4271 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4272 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4273 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4276 SIVAL(outbuf,smb_vwv6,0);
4277 SIVAL(outbuf,smb_vwv8,0);
4279 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4280 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4282 SSVAL(outbuf,smb_vwv10, mode);
4284 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4286 END_PROFILE(SMBgetattrE);