2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Reply to an special message.
43 ****************************************************************************/
45 int reply_special(char *inbuf,char *outbuf)
48 int msg_type = CVAL(inbuf,0);
49 int msg_flags = CVAL(inbuf,1);
55 static BOOL already_got_session = False;
59 memset(outbuf,'\0',smb_size);
64 case 0x81: /* session request */
66 if (already_got_session) {
67 exit_server("multiple session request not permitted");
72 if (name_len(inbuf+4) > 50 ||
73 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
74 DEBUG(0,("Invalid name length in session request\n"));
77 name_extract(inbuf,4,name1);
78 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
79 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
86 name_type = name2[15];
90 set_local_machine_name(name1, True);
91 set_remote_machine_name(name2, True);
93 DEBUG(2,("netbios connect: local=%s remote=%s\n",
94 get_local_machine_name(), get_remote_machine_name() ));
96 if (name_type == 'R') {
97 /* We are being asked for a pathworks session ---
99 SCVAL(outbuf, 0,0x83);
103 /* only add the client's machine name to the list
104 of possibly valid usernames if we are operating
105 in share mode security */
106 if (lp_security() == SEC_SHARE) {
107 add_session_user(get_remote_machine_name());
110 reload_services(True);
113 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
115 already_got_session = True;
118 case 0x89: /* session keepalive request
119 (some old clients produce this?) */
120 SCVAL(outbuf,0,SMBkeepalive);
124 case 0x82: /* positive session response */
125 case 0x83: /* negative session response */
126 case 0x84: /* retarget session response */
127 DEBUG(0,("Unexpected session response\n"));
130 case SMBkeepalive: /* session keepalive */
135 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
136 msg_type, msg_flags));
141 /****************************************************************************
143 ****************************************************************************/
145 int reply_tcon(connection_struct *conn,
146 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
153 uint16 vuid = SVAL(inbuf,smb_uid);
157 DATA_BLOB password_blob;
159 START_PROFILE(SMBtcon);
161 *service_buf = *password = *dev = 0;
163 p = smb_buf(inbuf)+1;
164 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
165 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
167 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
169 p = strrchr_m(service_buf,'\\');
173 service = service_buf;
176 password_blob = data_blob(password, pwlen+1);
178 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
180 data_blob_clear_free(&password_blob);
183 END_PROFILE(SMBtcon);
184 return ERROR_NT(nt_status);
187 outsize = set_message(outbuf,2,0,True);
188 SSVAL(outbuf,smb_vwv0,max_recv);
189 SSVAL(outbuf,smb_vwv1,conn->cnum);
190 SSVAL(outbuf,smb_tid,conn->cnum);
192 DEBUG(3,("tcon service=%s cnum=%d\n",
193 service, conn->cnum));
195 END_PROFILE(SMBtcon);
199 /****************************************************************************
200 Reply to a tcon and X.
201 ****************************************************************************/
203 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
209 uint16 vuid = SVAL(inbuf,smb_uid);
210 int passlen = SVAL(inbuf,smb_vwv3);
213 extern BOOL global_encrypted_passwords_negotiated;
214 START_PROFILE(SMBtconX);
216 *service = *devicename = 0;
218 /* we might have to close an old one */
219 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
220 close_cnum(conn,vuid);
223 if (passlen > MAX_PASS_LEN) {
224 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
227 if (global_encrypted_passwords_negotiated) {
228 password = data_blob(smb_buf(inbuf),passlen);
230 password = data_blob(smb_buf(inbuf),passlen+1);
231 /* Ensure correct termination */
232 password.data[passlen]=0;
235 p = smb_buf(inbuf) + passlen;
236 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
239 * the service name can be either: \\server\share
240 * or share directly like on the DELL PowerVault 705
243 q = strchr_m(path+2,'\\');
245 END_PROFILE(SMBtconX);
246 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
248 fstrcpy(service,q+1);
251 fstrcpy(service,path);
253 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
255 DEBUG(4,("Got device type %s\n",devicename));
257 conn = make_connection(service,password,devicename,vuid,&nt_status);
259 data_blob_clear_free(&password);
262 END_PROFILE(SMBtconX);
263 return ERROR_NT(nt_status);
266 if (Protocol < PROTOCOL_NT1) {
267 set_message(outbuf,2,0,True);
269 p += srvstr_push(outbuf, p, devicename, -1,
270 STR_TERMINATE|STR_ASCII);
271 set_message_end(outbuf,p);
273 /* NT sets the fstype of IPC$ to the null string */
274 const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
275 const char *devicetype;
277 set_message(outbuf,3,0,True);
281 else if ( IS_PRINT(conn) )
287 p += srvstr_push(outbuf, p, IS_IPC(conn) ? "IPC" : devicetype, -1,
288 STR_TERMINATE|STR_ASCII);
289 p += srvstr_push(outbuf, p, fsname, -1,
292 p += srvstr_push(outbuf, p, IS_IPC(conn) ? "IPC" : devicename, -1,
293 STR_TERMINATE|STR_ASCII);
294 p += srvstr_push(outbuf, p, fsname, -1,
297 set_message_end(outbuf,p);
299 /* what does setting this bit do? It is set by NT4 and
300 may affect the ability to autorun mounted cdroms */
301 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
302 (lp_csc_policy(SNUM(conn)) << 2));
304 init_dfsroot(conn, inbuf, outbuf);
308 DEBUG(3,("tconX service=%s \n",
311 /* set the incoming and outgoing tid to the just created one */
312 SSVAL(inbuf,smb_tid,conn->cnum);
313 SSVAL(outbuf,smb_tid,conn->cnum);
315 END_PROFILE(SMBtconX);
316 return chain_reply(inbuf,outbuf,length,bufsize);
319 /****************************************************************************
320 Reply to an unknown type.
321 ****************************************************************************/
323 int reply_unknown(char *inbuf,char *outbuf)
326 type = CVAL(inbuf,smb_com);
328 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
329 smb_fn_name(type), type, type));
331 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
334 /****************************************************************************
336 ****************************************************************************/
338 int reply_ioctl(connection_struct *conn,
339 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
341 uint16 device = SVAL(inbuf,smb_vwv1);
342 uint16 function = SVAL(inbuf,smb_vwv2);
343 uint32 ioctl_code = (device << 16) + function;
344 int replysize, outsize;
346 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
347 START_PROFILE(SMBioctl);
349 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
351 switch (ioctl_code) {
352 case IOCTL_QUERY_JOB_INFO:
356 END_PROFILE(SMBioctl);
357 return(ERROR_DOS(ERRSRV,ERRnosupport));
360 outsize = set_message(outbuf,8,replysize+1,True);
361 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
362 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
363 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
364 p = smb_buf(outbuf) + 1; /* Allow for alignment */
366 switch (ioctl_code) {
367 case IOCTL_QUERY_JOB_INFO:
369 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
370 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
371 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
376 END_PROFILE(SMBioctl);
380 /****************************************************************************
382 ****************************************************************************/
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 if (!(ok = S_ISDIR(sbuf.st_mode)))
409 /* We special case this - as when a Windows machine
410 is parsing a path is steps through the components
411 one at a time - if a component fails it expects
412 ERRbadpath, not ERRbadfile.
415 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);
428 /****************************************************************************
430 ****************************************************************************/
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! */
453 mode = aHIDDEN | aDIR;
454 if (!CAN_WRITE(conn))
460 unix_convert(fname,conn,0,&bad_path,&sbuf);
461 if (check_name(fname,conn)) {
462 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) {
463 mode = dos_mode(conn,fname,&sbuf);
465 mtime = sbuf.st_mtime;
470 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
476 set_bad_path_error(errno, bad_path);
477 END_PROFILE(SMBgetatr);
478 return(UNIXERROR(ERRDOS,ERRbadfile));
481 outsize = set_message(outbuf,10,0,True);
483 SSVAL(outbuf,smb_vwv0,mode);
484 if(lp_dos_filetime_resolution(SNUM(conn)) )
485 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
487 put_dos_date3(outbuf,smb_vwv1,mtime);
488 SIVAL(outbuf,smb_vwv3,(uint32)size);
490 if (Protocol >= PROTOCOL_NT1)
491 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
493 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
495 END_PROFILE(SMBgetatr);
499 /****************************************************************************
501 ****************************************************************************/
503 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
510 SMB_STRUCT_STAT sbuf;
511 BOOL bad_path = False;
514 START_PROFILE(SMBsetatr);
516 p = smb_buf(inbuf) + 1;
517 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
518 unix_convert(fname,conn,0,&bad_path,&sbuf);
520 mode = SVAL(inbuf,smb_vwv0);
521 mtime = make_unix_date3(inbuf+smb_vwv1);
523 if (VALID_STAT_OF_DIR(sbuf))
528 if (check_name(fname,conn))
529 ok = (file_chmod(conn,fname,mode,NULL) == 0);
531 ok = set_filetime(conn,fname,mtime);
534 set_bad_path_error(errno, bad_path);
535 END_PROFILE(SMBsetatr);
536 return(UNIXERROR(ERRDOS,ERRnoaccess));
539 outsize = set_message(outbuf,0,0,True);
541 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
543 END_PROFILE(SMBsetatr);
547 /****************************************************************************
549 ****************************************************************************/
551 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
554 SMB_BIG_UINT dfree,dsize,bsize;
555 START_PROFILE(SMBdskattr);
557 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
559 outsize = set_message(outbuf,5,0,True);
561 if (Protocol <= PROTOCOL_LANMAN2) {
562 double total_space, free_space;
563 /* we need to scale this to a number that DOS6 can handle. We
564 use floating point so we can handle large drives on systems
565 that don't have 64 bit integers
567 we end up displaying a maximum of 2G to DOS systems
569 total_space = dsize * (double)bsize;
570 free_space = dfree * (double)bsize;
572 dsize = (total_space+63*512) / (64*512);
573 dfree = (free_space+63*512) / (64*512);
575 if (dsize > 0xFFFF) dsize = 0xFFFF;
576 if (dfree > 0xFFFF) dfree = 0xFFFF;
578 SSVAL(outbuf,smb_vwv0,dsize);
579 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
580 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
581 SSVAL(outbuf,smb_vwv3,dfree);
583 SSVAL(outbuf,smb_vwv0,dsize);
584 SSVAL(outbuf,smb_vwv1,bsize/512);
585 SSVAL(outbuf,smb_vwv2,512);
586 SSVAL(outbuf,smb_vwv3,dfree);
589 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
591 END_PROFILE(SMBdskattr);
595 /****************************************************************************
597 Can be called from SMBsearch, SMBffirst or SMBfunique.
598 ****************************************************************************/
600 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
611 BOOL finished = False;
620 BOOL check_descend = False;
621 BOOL expect_close = False;
622 BOOL can_open = True;
623 BOOL bad_path = False;
624 START_PROFILE(SMBsearch);
626 *mask = *directory = *fname = 0;
628 /* If we were called as SMBffirst then we must expect close. */
629 if(CVAL(inbuf,smb_com) == SMBffirst)
632 outsize = set_message(outbuf,1,3,True);
633 maxentries = SVAL(inbuf,smb_vwv0);
634 dirtype = SVAL(inbuf,smb_vwv1);
635 p = smb_buf(inbuf) + 1;
636 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
638 status_len = SVAL(p, 0);
641 /* dirtype &= ~aDIR; */
643 if (status_len == 0) {
644 SMB_STRUCT_STAT sbuf;
647 pstrcpy(directory,path);
649 unix_convert(directory,conn,0,&bad_path,&sbuf);
652 if (!check_name(directory,conn))
655 p = strrchr_m(dir2,'/');
664 p = strrchr_m(directory,'/');
670 if (strlen(directory) == 0)
671 pstrcpy(directory,".");
672 memset((char *)status,'\0',21);
673 SCVAL(status,0,(dirtype & 0x1F));
678 status_dirtype = CVAL(status,0) & 0x1F;
679 if (status_dirtype != (dirtype & 0x1F))
680 dirtype = status_dirtype;
682 conn->dirptr = dptr_fetch(status+12,&dptr_num);
685 string_set(&conn->dirpath,dptr_path(dptr_num));
686 pstrcpy(mask, dptr_wcard(dptr_num));
690 p = smb_buf(outbuf) + 3;
693 if (status_len == 0) {
694 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
697 set_bad_path_error(errno, bad_path);
698 END_PROFILE(SMBsearch);
699 return (UNIXERROR(ERRDOS,ERRnofids));
701 END_PROFILE(SMBsearch);
702 return ERROR_DOS(ERRDOS,ERRnofids);
704 dptr_set_wcard(dptr_num, strdup(mask));
705 dptr_set_attr(dptr_num, dirtype);
707 dirtype = dptr_attr(dptr_num);
710 DEBUG(4,("dptr_num is %d\n",dptr_num));
713 if ((dirtype&0x1F) == aVOLID) {
715 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
716 dptr_fill(p+12,dptr_num);
717 if (dptr_zero(p+12) && (status_len==0))
721 p += DIR_STRUCT_SIZE;
723 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
724 conn->dirpath,lp_dontdescend(SNUM(conn))));
725 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
726 check_descend = True;
728 for (i=numentries;(i<maxentries) && !finished;i++) {
729 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
732 make_dir_struct(p,mask,fname,size,mode,date);
733 dptr_fill(p+12,dptr_num);
736 p += DIR_STRUCT_SIZE;
745 if (numentries == 0 || !ok) {
746 SCVAL(outbuf,smb_rcls,ERRDOS);
747 SSVAL(outbuf,smb_err,ERRnofiles);
748 dptr_close(&dptr_num);
751 /* If we were called as SMBffirst with smb_search_id == NULL
752 and no entries were found then return error and close dirptr
755 if(ok && expect_close && numentries == 0 && status_len == 0) {
756 SCVAL(outbuf,smb_rcls,ERRDOS);
757 SSVAL(outbuf,smb_err,ERRnofiles);
758 /* Also close the dptr - we know it's gone */
759 dptr_close(&dptr_num);
762 /* If we were called as SMBfunique, then we can close the dirptr now ! */
763 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
764 dptr_close(&dptr_num);
766 SSVAL(outbuf,smb_vwv0,numentries);
767 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
768 SCVAL(smb_buf(outbuf),0,5);
769 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
771 if (Protocol >= PROTOCOL_NT1)
772 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
774 outsize += DIR_STRUCT_SIZE*numentries;
775 smb_setlen(outbuf,outsize - 4);
777 if ((! *directory) && dptr_path(dptr_num))
778 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
780 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
781 smb_fn_name(CVAL(inbuf,smb_com)),
782 mask, directory, dirtype, numentries, maxentries ) );
784 END_PROFILE(SMBsearch);
788 /****************************************************************************
789 Reply to a fclose (stop directory search).
790 ****************************************************************************/
792 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
801 START_PROFILE(SMBfclose);
803 outsize = set_message(outbuf,1,0,True);
804 p = smb_buf(inbuf) + 1;
805 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
807 status_len = SVAL(p,0);
810 if (status_len == 0) {
811 END_PROFILE(SMBfclose);
812 return ERROR_DOS(ERRSRV,ERRsrverror);
817 if(dptr_fetch(status+12,&dptr_num)) {
818 /* Close the dptr - we know it's gone */
819 dptr_close(&dptr_num);
822 SSVAL(outbuf,smb_vwv0,0);
824 DEBUG(3,("search close\n"));
826 END_PROFILE(SMBfclose);
830 /****************************************************************************
832 ****************************************************************************/
834 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
844 SMB_STRUCT_STAT sbuf;
845 BOOL bad_path = False;
847 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
848 START_PROFILE(SMBopen);
850 share_mode = SVAL(inbuf,smb_vwv0);
852 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
854 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
856 unix_convert(fname,conn,0,&bad_path,&sbuf);
858 unixmode = unix_mode(conn,aARCH,fname);
860 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
861 unixmode, oplock_request,&rmode,NULL);
864 set_bad_path_error(errno, bad_path);
865 END_PROFILE(SMBopen);
866 return(UNIXERROR(ERRDOS,ERRnoaccess));
870 fmode = dos_mode(conn,fname,&sbuf);
871 mtime = sbuf.st_mtime;
874 DEBUG(3,("attempt to open a directory %s\n",fname));
875 close_file(fsp,False);
876 END_PROFILE(SMBopen);
877 return ERROR_DOS(ERRDOS,ERRnoaccess);
880 outsize = set_message(outbuf,7,0,True);
881 SSVAL(outbuf,smb_vwv0,fsp->fnum);
882 SSVAL(outbuf,smb_vwv1,fmode);
883 if(lp_dos_filetime_resolution(SNUM(conn)) )
884 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
886 put_dos_date3(outbuf,smb_vwv2,mtime);
887 SIVAL(outbuf,smb_vwv4,(uint32)size);
888 SSVAL(outbuf,smb_vwv6,rmode);
890 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
891 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
893 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
894 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
895 END_PROFILE(SMBopen);
899 /****************************************************************************
900 Reply to an open and X.
901 ****************************************************************************/
903 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
906 int smb_mode = SVAL(inbuf,smb_vwv3);
907 int smb_attr = SVAL(inbuf,smb_vwv5);
908 /* Breakout the oplock request bits so we can set the
909 reply bits separately. */
910 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
911 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
912 BOOL oplock_request = ex_oplock_request | core_oplock_request;
914 int open_flags = SVAL(inbuf,smb_vwv2);
915 int smb_sattr = SVAL(inbuf,smb_vwv4);
916 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
918 int smb_ofun = SVAL(inbuf,smb_vwv8);
921 int fmode=0,mtime=0,rmode=0;
922 SMB_STRUCT_STAT sbuf;
924 BOOL bad_path = False;
926 START_PROFILE(SMBopenX);
928 /* If it's an IPC, pass off the pipe handler. */
930 if (lp_nt_pipe_support()) {
931 END_PROFILE(SMBopenX);
932 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
934 END_PROFILE(SMBopenX);
935 return ERROR_DOS(ERRSRV,ERRaccess);
939 /* XXXX we need to handle passed times, sattr and flags */
940 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
942 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
944 unix_convert(fname,conn,0,&bad_path,&sbuf);
946 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
948 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
949 oplock_request, &rmode,&smb_action);
952 set_bad_path_error(errno, bad_path);
953 END_PROFILE(SMBopenX);
954 return(UNIXERROR(ERRDOS,ERRnoaccess));
958 fmode = dos_mode(conn,fname,&sbuf);
959 mtime = sbuf.st_mtime;
961 close_file(fsp,False);
962 END_PROFILE(SMBopenX);
963 return ERROR_DOS(ERRDOS,ERRnoaccess);
966 /* If the caller set the extended oplock request bit
967 and we granted one (by whatever means) - set the
968 correct bit for extended oplock reply.
971 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
972 smb_action |= EXTENDED_OPLOCK_GRANTED;
974 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
975 smb_action |= EXTENDED_OPLOCK_GRANTED;
977 /* If the caller set the core oplock request bit
978 and we granted one (by whatever means) - set the
979 correct bit for core oplock reply.
982 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
983 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
985 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
986 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
988 set_message(outbuf,15,0,True);
989 SSVAL(outbuf,smb_vwv2,fsp->fnum);
990 SSVAL(outbuf,smb_vwv3,fmode);
991 if(lp_dos_filetime_resolution(SNUM(conn)) )
992 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
994 put_dos_date3(outbuf,smb_vwv4,mtime);
995 SIVAL(outbuf,smb_vwv6,(uint32)size);
996 SSVAL(outbuf,smb_vwv8,rmode);
997 SSVAL(outbuf,smb_vwv11,smb_action);
999 END_PROFILE(SMBopenX);
1000 return chain_reply(inbuf,outbuf,length,bufsize);
1003 /****************************************************************************
1004 Reply to a SMBulogoffX.
1005 ****************************************************************************/
1007 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1009 uint16 vuid = SVAL(inbuf,smb_uid);
1010 user_struct *vuser = get_valid_user_struct(vuid);
1011 START_PROFILE(SMBulogoffX);
1014 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1016 /* in user level security we are supposed to close any files
1017 open by this user */
1018 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1019 file_close_user(vuid);
1021 invalidate_vuid(vuid);
1023 set_message(outbuf,2,0,True);
1025 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1027 END_PROFILE(SMBulogoffX);
1028 return chain_reply(inbuf,outbuf,length,bufsize);
1031 /****************************************************************************
1032 Reply to a mknew or a create.
1033 ****************************************************************************/
1035 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1043 BOOL bad_path = False;
1045 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1046 SMB_STRUCT_STAT sbuf;
1047 START_PROFILE(SMBcreate);
1049 com = SVAL(inbuf,smb_com);
1051 createmode = SVAL(inbuf,smb_vwv0);
1052 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1054 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1056 unix_convert(fname,conn,0,&bad_path,&sbuf);
1058 if (createmode & aVOLID)
1059 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1061 unixmode = unix_mode(conn,createmode,fname);
1063 if(com == SMBmknew) {
1064 /* We should fail if file exists. */
1065 ofun = FILE_CREATE_IF_NOT_EXIST;
1067 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1068 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1071 /* Open file in dos compatibility share mode. */
1072 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1073 ofun, unixmode, oplock_request, NULL, NULL);
1076 set_bad_path_error(errno, bad_path);
1077 END_PROFILE(SMBcreate);
1078 return(UNIXERROR(ERRDOS,ERRnoaccess));
1081 outsize = set_message(outbuf,1,0,True);
1082 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1084 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1085 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1087 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1088 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1090 DEBUG( 2, ( "new file %s\n", fname ) );
1091 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1093 END_PROFILE(SMBcreate);
1097 /****************************************************************************
1098 Reply to a create temporary file.
1099 ****************************************************************************/
1101 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1107 BOOL bad_path = False;
1109 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1111 SMB_STRUCT_STAT sbuf;
1114 START_PROFILE(SMBctemp);
1116 createmode = SVAL(inbuf,smb_vwv0);
1117 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1118 pstrcat(fname,"\\TMXXXXXX");
1120 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1122 unix_convert(fname,conn,0,&bad_path,&sbuf);
1124 unixmode = unix_mode(conn,createmode,fname);
1126 tmpfd = smb_mkstemp(fname);
1128 END_PROFILE(SMBctemp);
1129 return(UNIXERROR(ERRDOS,ERRnoaccess));
1132 vfs_stat(conn,fname,&sbuf);
1134 /* Open file in dos compatibility share mode. */
1135 /* We should fail if file does not exist. */
1136 fsp = open_file_shared(conn,fname,&sbuf,
1137 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1138 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1139 unixmode, oplock_request, NULL, NULL);
1141 /* close fd from smb_mkstemp() */
1145 set_bad_path_error(errno, bad_path);
1146 END_PROFILE(SMBctemp);
1147 return(UNIXERROR(ERRDOS,ERRnoaccess));
1150 outsize = set_message(outbuf,1,0,True);
1151 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1153 /* the returned filename is relative to the directory */
1154 s = strrchr_m(fname, '/');
1160 p = smb_buf(outbuf);
1161 SSVALS(p, 0, -1); /* what is this? not in spec */
1162 SSVAL(p, 2, strlen(s));
1164 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1165 outsize = set_message_end(outbuf, p);
1167 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1168 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1170 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1171 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1173 DEBUG( 2, ( "created temp file %s\n", fname ) );
1174 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1175 fname, fsp->fd, createmode, (int)unixmode ) );
1177 END_PROFILE(SMBctemp);
1181 /*******************************************************************
1182 Check if a user is allowed to rename a file.
1183 ********************************************************************/
1185 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1191 if (!CAN_WRITE(conn))
1192 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1194 if (S_ISDIR(pst->st_mode))
1195 return NT_STATUS_OK;
1197 /* We need a better way to return NT status codes from open... */
1201 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1202 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1205 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1206 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1207 ret = NT_STATUS_SHARING_VIOLATION;
1212 close_file(fsp,False);
1213 return NT_STATUS_OK;
1216 /*******************************************************************
1217 Check if a user is allowed to delete a file.
1218 ********************************************************************/
1220 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1222 SMB_STRUCT_STAT sbuf;
1228 if (!CAN_WRITE(conn))
1229 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1231 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1232 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1234 fmode = dos_mode(conn,fname,&sbuf);
1236 return NT_STATUS_FILE_IS_A_DIRECTORY;
1237 if (!lp_delete_readonly(SNUM(conn))) {
1239 return NT_STATUS_CANNOT_DELETE;
1241 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1242 return NT_STATUS_CANNOT_DELETE;
1244 /* We need a better way to return NT status codes from open... */
1248 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1249 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1252 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1253 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1254 ret = unix_ERR_ntstatus;
1255 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1256 ret = NT_STATUS_SHARING_VIOLATION;
1259 unix_ERR_ntstatus = NT_STATUS_OK;
1262 close_file(fsp,False);
1263 return NT_STATUS_OK;
1266 /****************************************************************************
1267 The guts of the unlink command, split out so it may be called by the NT SMB
1269 ****************************************************************************/
1271 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1277 NTSTATUS error = NT_STATUS_OK;
1279 BOOL bad_path = False;
1281 SMB_STRUCT_STAT sbuf;
1283 *directory = *mask = 0;
1285 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1287 p = strrchr_m(name,'/');
1289 pstrcpy(directory,".");
1293 pstrcpy(directory,name);
1298 * We should only check the mangled cache
1299 * here if unix_convert failed. This means
1300 * that the path in 'mask' doesn't exist
1301 * on the file system and so we need to look
1302 * for a possible mangle. This patch from
1303 * Tine Smukavec <valentin.smukavec@hermes.si>.
1306 if (!rc && mangle_is_mangled(mask))
1307 mangle_check_cache( mask );
1309 has_wild = ms_has_wild(mask);
1312 pstrcat(directory,"/");
1313 pstrcat(directory,mask);
1314 error = can_delete(directory,conn,dirtype);
1315 if (!NT_STATUS_IS_OK(error)) return error;
1317 if (vfs_unlink(conn,directory) == 0) {
1321 void *dirptr = NULL;
1324 if (check_name(directory,conn))
1325 dirptr = OpenDir(conn, directory, True);
1327 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1328 the pattern matches against the long name, otherwise the short name
1329 We don't implement this yet XXXX
1333 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1335 if (strequal(mask,"????????.???"))
1338 while ((dname = ReadDirName(dirptr))) {
1340 pstrcpy(fname,dname);
1342 if(!mask_match(fname, mask, case_sensitive)) continue;
1344 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1345 error = can_delete(fname,conn,dirtype);
1346 if (!NT_STATUS_IS_OK(error)) continue;
1347 if (vfs_unlink(conn,fname) == 0) count++;
1348 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1354 if (count == 0 && NT_STATUS_IS_OK(error)) {
1355 error = map_nt_error_from_unix(errno);
1361 /****************************************************************************
1363 ****************************************************************************/
1365 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1372 START_PROFILE(SMBunlink);
1374 dirtype = SVAL(inbuf,smb_vwv0);
1376 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1378 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1380 DEBUG(3,("reply_unlink : %s\n",name));
1382 status = unlink_internals(conn, dirtype, name);
1383 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1386 * Win2k needs a changenotify request response before it will
1387 * update after a rename..
1389 process_pending_change_notify_queue((time_t)0);
1391 outsize = set_message(outbuf,0,0,True);
1393 END_PROFILE(SMBunlink);
1397 /****************************************************************************
1399 ****************************************************************************/
1401 void fail_readraw(void)
1404 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1406 exit_server(errstr);
1409 /****************************************************************************
1410 Use sendfile in readbraw.
1411 ****************************************************************************/
1413 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1414 ssize_t mincount, char *outbuf)
1418 #if defined(WITH_SENDFILE)
1420 * We can only use sendfile on a non-chained packet and on a file
1421 * that is exclusively oplocked. reply_readbraw has already checked the length.
1424 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1425 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1428 _smb_setlen(outbuf,nread);
1429 header.data = outbuf;
1433 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1435 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1436 * return ENOSYS then pretend we just got a normal read.
1438 if (errno == ENOSYS)
1441 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1442 fsp->fsp_name, strerror(errno) ));
1443 exit_server("send_file_readbraw sendfile failed");
1452 ret = read_file(fsp,outbuf+4,startpos,nread);
1457 _smb_setlen(outbuf,ret);
1458 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1462 /****************************************************************************
1463 Reply to a readbraw (core+ protocol).
1464 ****************************************************************************/
1466 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1468 ssize_t maxcount,mincount;
1471 char *header = outbuf;
1473 START_PROFILE(SMBreadbraw);
1476 * Special check if an oplock break has been issued
1477 * and the readraw request croses on the wire, we must
1478 * return a zero length response here.
1481 if(global_oplock_break) {
1482 _smb_setlen(header,0);
1483 if (write_data(smbd_server_fd(),header,4) != 4)
1485 DEBUG(5,("readbraw - oplock break finished\n"));
1486 END_PROFILE(SMBreadbraw);
1490 fsp = file_fsp(inbuf,smb_vwv0);
1492 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1494 * fsp could be NULL here so use the value from the packet. JRA.
1496 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1497 _smb_setlen(header,0);
1498 if (write_data(smbd_server_fd(),header,4) != 4)
1500 END_PROFILE(SMBreadbraw);
1504 CHECK_FSP(fsp,conn);
1506 flush_write_cache(fsp, READRAW_FLUSH);
1508 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1509 if(CVAL(inbuf,smb_wct) == 10) {
1511 * This is a large offset (64 bit) read.
1513 #ifdef LARGE_SMB_OFF_T
1515 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1517 #else /* !LARGE_SMB_OFF_T */
1520 * Ensure we haven't been sent a >32 bit offset.
1523 if(IVAL(inbuf,smb_vwv8) != 0) {
1524 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1525 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1526 _smb_setlen(header,0);
1527 if (write_data(smbd_server_fd(),header,4) != 4)
1529 END_PROFILE(SMBreadbraw);
1533 #endif /* LARGE_SMB_OFF_T */
1536 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1537 _smb_setlen(header,0);
1538 if (write_data(smbd_server_fd(),header,4) != 4)
1540 END_PROFILE(SMBreadbraw);
1544 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1545 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1547 /* ensure we don't overrun the packet size */
1548 maxcount = MIN(65535,maxcount);
1549 maxcount = MAX(mincount,maxcount);
1551 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1552 SMB_OFF_T size = fsp->size;
1553 SMB_OFF_T sizeneeded = startpos + maxcount;
1555 if (size < sizeneeded) {
1557 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1559 if (!fsp->can_write)
1563 if (startpos >= size)
1566 nread = MIN(maxcount,(size - startpos));
1569 if (nread < mincount)
1572 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1573 (int)maxcount, (int)mincount, (int)nread ) );
1575 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1577 DEBUG(5,("readbraw finished\n"));
1578 END_PROFILE(SMBreadbraw);
1582 /****************************************************************************
1583 Reply to a lockread (core+ protocol).
1584 ****************************************************************************/
1586 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1594 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1595 START_PROFILE(SMBlockread);
1597 CHECK_FSP(fsp,conn);
1600 release_level_2_oplocks_on_change(fsp);
1602 numtoread = SVAL(inbuf,smb_vwv1);
1603 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1605 outsize = set_message(outbuf,5,3,True);
1606 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1607 data = smb_buf(outbuf) + 3;
1610 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1611 * protocol request that predates the read/write lock concept.
1612 * Thus instead of asking for a read lock here we need to ask
1613 * for a write lock. JRA.
1616 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1617 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1619 if (NT_STATUS_V(status)) {
1620 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1622 * A blocking lock was requested. Package up
1623 * this smb into a queued request and push it
1624 * onto the blocking lock queue.
1626 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1627 (SMB_BIG_UINT)numtoread)) {
1628 END_PROFILE(SMBlockread);
1632 END_PROFILE(SMBlockread);
1633 return ERROR_NT(status);
1636 nread = read_file(fsp,data,startpos,numtoread);
1639 END_PROFILE(SMBlockread);
1640 return(UNIXERROR(ERRDOS,ERRnoaccess));
1644 SSVAL(outbuf,smb_vwv0,nread);
1645 SSVAL(outbuf,smb_vwv5,nread+3);
1646 SSVAL(smb_buf(outbuf),1,nread);
1648 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1649 fsp->fnum, (int)numtoread, (int)nread));
1651 END_PROFILE(SMBlockread);
1655 /****************************************************************************
1657 ****************************************************************************/
1659 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1666 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1667 START_PROFILE(SMBread);
1669 CHECK_FSP(fsp,conn);
1672 numtoread = SVAL(inbuf,smb_vwv1);
1673 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1675 outsize = set_message(outbuf,5,3,True);
1676 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1677 data = smb_buf(outbuf) + 3;
1679 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1680 END_PROFILE(SMBread);
1681 return ERROR_DOS(ERRDOS,ERRlock);
1685 nread = read_file(fsp,data,startpos,numtoread);
1688 END_PROFILE(SMBread);
1689 return(UNIXERROR(ERRDOS,ERRnoaccess));
1693 SSVAL(outbuf,smb_vwv0,nread);
1694 SSVAL(outbuf,smb_vwv5,nread+3);
1695 SCVAL(smb_buf(outbuf),0,1);
1696 SSVAL(smb_buf(outbuf),1,nread);
1698 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1699 fsp->fnum, (int)numtoread, (int)nread ) );
1701 END_PROFILE(SMBread);
1705 /****************************************************************************
1706 Reply to a read and X - possibly using sendfile.
1707 ****************************************************************************/
1709 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1710 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1713 char *data = smb_buf(outbuf);
1715 #if defined(WITH_SENDFILE)
1717 * We can only use sendfile on a non-chained packet and on a file
1718 * that is exclusively oplocked.
1721 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1722 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1723 SMB_STRUCT_STAT sbuf;
1726 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
1727 return(UNIXERROR(ERRDOS,ERRnoaccess));
1729 if (startpos > sbuf.st_size)
1732 if (smb_maxcnt > (sbuf.st_size - startpos))
1733 smb_maxcnt = (sbuf.st_size - startpos);
1735 if (smb_maxcnt == 0)
1739 * Set up the packet header before send. We
1740 * assume here the sendfile will work (get the
1741 * correct amount of data).
1744 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1745 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1746 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1747 SCVAL(outbuf,smb_vwv0,0xFF);
1748 set_message(outbuf,12,smb_maxcnt,False);
1749 header.data = outbuf;
1750 header.length = data - outbuf;
1753 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1755 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1756 * return ENOSYS then pretend we just got a normal read.
1758 if (errno == ENOSYS)
1761 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1762 fsp->fsp_name, strerror(errno) ));
1763 exit_server("send_file_readX sendfile failed");
1766 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1767 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1775 nread = read_file(fsp,data,startpos,smb_maxcnt);
1778 END_PROFILE(SMBreadX);
1779 return(UNIXERROR(ERRDOS,ERRnoaccess));
1782 SSVAL(outbuf,smb_vwv5,nread);
1783 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1784 SSVAL(smb_buf(outbuf),-2,nread);
1786 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1787 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1792 /****************************************************************************
1793 Reply to a read and X.
1794 ****************************************************************************/
1796 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1798 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1799 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1801 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1803 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1806 START_PROFILE(SMBreadX);
1808 /* If it's an IPC, pass off the pipe handler. */
1810 END_PROFILE(SMBreadX);
1811 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1814 CHECK_FSP(fsp,conn);
1817 set_message(outbuf,12,0,True);
1819 if(CVAL(inbuf,smb_wct) == 12) {
1820 #ifdef LARGE_SMB_OFF_T
1822 * This is a large offset (64 bit) read.
1824 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1826 #else /* !LARGE_SMB_OFF_T */
1829 * Ensure we haven't been sent a >32 bit offset.
1832 if(IVAL(inbuf,smb_vwv10) != 0) {
1833 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1834 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1835 END_PROFILE(SMBreadX);
1836 return ERROR_DOS(ERRDOS,ERRbadaccess);
1839 #endif /* LARGE_SMB_OFF_T */
1843 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1844 END_PROFILE(SMBreadX);
1845 return ERROR_DOS(ERRDOS,ERRlock);
1848 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1850 nread = chain_reply(inbuf,outbuf,length,bufsize);
1852 END_PROFILE(SMBreadX);
1856 /****************************************************************************
1857 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1858 ****************************************************************************/
1860 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1863 ssize_t total_written=0;
1864 size_t numtowrite=0;
1869 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1871 START_PROFILE(SMBwritebraw);
1873 CHECK_FSP(fsp,conn);
1876 tcount = IVAL(inbuf,smb_vwv1);
1877 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1878 write_through = BITSETW(inbuf+smb_vwv7,0);
1880 /* We have to deal with slightly different formats depending
1881 on whether we are using the core+ or lanman1.0 protocol */
1883 if(Protocol <= PROTOCOL_COREPLUS) {
1884 numtowrite = SVAL(smb_buf(inbuf),-2);
1885 data = smb_buf(inbuf);
1887 numtowrite = SVAL(inbuf,smb_vwv10);
1888 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1891 /* force the error type */
1892 SCVAL(inbuf,smb_com,SMBwritec);
1893 SCVAL(outbuf,smb_com,SMBwritec);
1895 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1896 END_PROFILE(SMBwritebraw);
1897 return(ERROR_DOS(ERRDOS,ERRlock));
1901 nwritten = write_file(fsp,data,startpos,numtowrite);
1903 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1904 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1906 if (nwritten < (ssize_t)numtowrite) {
1907 END_PROFILE(SMBwritebraw);
1908 return(UNIXERROR(ERRHRD,ERRdiskfull));
1911 total_written = nwritten;
1913 /* Return a message to the redirector to tell it to send more bytes */
1914 SCVAL(outbuf,smb_com,SMBwritebraw);
1915 SSVALS(outbuf,smb_vwv0,-1);
1916 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1917 if (!send_smb(smbd_server_fd(),outbuf))
1918 exit_server("reply_writebraw: send_smb failed.");
1920 /* Now read the raw data into the buffer and write it */
1921 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1922 exit_server("secondary writebraw failed");
1925 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1926 numtowrite = smb_len(inbuf);
1928 /* Set up outbuf to return the correct return */
1929 outsize = set_message(outbuf,1,0,True);
1930 SCVAL(outbuf,smb_com,SMBwritec);
1931 SSVAL(outbuf,smb_vwv0,total_written);
1933 if (numtowrite != 0) {
1935 if (numtowrite > BUFFER_SIZE) {
1936 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1937 (unsigned int)numtowrite ));
1938 exit_server("secondary writebraw failed");
1941 if (tcount > nwritten+numtowrite) {
1942 DEBUG(3,("Client overestimated the write %d %d %d\n",
1943 (int)tcount,(int)nwritten,(int)numtowrite));
1946 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1947 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1949 exit_server("secondary writebraw failed");
1952 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1954 if (nwritten < (ssize_t)numtowrite) {
1955 SCVAL(outbuf,smb_rcls,ERRHRD);
1956 SSVAL(outbuf,smb_err,ERRdiskfull);
1960 total_written += nwritten;
1963 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1964 sync_file(conn,fsp);
1966 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1967 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1969 /* we won't return a status if write through is not selected - this follows what WfWg does */
1970 END_PROFILE(SMBwritebraw);
1971 if (!write_through && total_written==tcount) {
1973 #if RABBIT_PELLET_FIX
1975 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1976 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1978 if (!send_keepalive(smbd_server_fd()))
1979 exit_server("reply_writebraw: send of keepalive failed");
1987 /****************************************************************************
1988 Reply to a writeunlock (core+).
1989 ****************************************************************************/
1991 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1992 int size, int dum_buffsize)
1994 ssize_t nwritten = -1;
1999 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2001 START_PROFILE(SMBwriteunlock);
2003 CHECK_FSP(fsp,conn);
2006 numtowrite = SVAL(inbuf,smb_vwv1);
2007 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2008 data = smb_buf(inbuf) + 3;
2010 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2011 WRITE_LOCK,False)) {
2012 END_PROFILE(SMBwriteunlock);
2013 return ERROR_DOS(ERRDOS,ERRlock);
2016 /* The special X/Open SMB protocol handling of
2017 zero length writes is *NOT* done for
2022 nwritten = write_file(fsp,data,startpos,numtowrite);
2024 if (lp_syncalways(SNUM(conn)))
2025 sync_file(conn,fsp);
2027 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2028 END_PROFILE(SMBwriteunlock);
2029 return(UNIXERROR(ERRHRD,ERRdiskfull));
2032 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2033 (SMB_BIG_UINT)startpos);
2034 if (NT_STATUS_V(status)) {
2035 END_PROFILE(SMBwriteunlock);
2036 return ERROR_NT(status);
2039 outsize = set_message(outbuf,1,0,True);
2041 SSVAL(outbuf,smb_vwv0,nwritten);
2043 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2044 fsp->fnum, (int)numtowrite, (int)nwritten));
2046 END_PROFILE(SMBwriteunlock);
2050 /****************************************************************************
2052 ****************************************************************************/
2054 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2057 ssize_t nwritten = -1;
2060 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2062 START_PROFILE(SMBwrite);
2064 /* If it's an IPC, pass off the pipe handler. */
2066 END_PROFILE(SMBwrite);
2067 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2070 CHECK_FSP(fsp,conn);
2073 numtowrite = SVAL(inbuf,smb_vwv1);
2074 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2075 data = smb_buf(inbuf) + 3;
2077 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2078 END_PROFILE(SMBwrite);
2079 return ERROR_DOS(ERRDOS,ERRlock);
2083 * X/Open SMB protocol says that if smb_vwv1 is
2084 * zero then the file size should be extended or
2085 * truncated to the size given in smb_vwv[2-3].
2088 if(numtowrite == 0) {
2090 * This is actually an allocate call, and set EOF. JRA.
2092 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2094 END_PROFILE(SMBwrite);
2095 return ERROR_NT(NT_STATUS_DISK_FULL);
2097 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2099 END_PROFILE(SMBwrite);
2100 return ERROR_NT(NT_STATUS_DISK_FULL);
2103 nwritten = write_file(fsp,data,startpos,numtowrite);
2105 if (lp_syncalways(SNUM(conn)))
2106 sync_file(conn,fsp);
2108 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2109 END_PROFILE(SMBwrite);
2110 return(UNIXERROR(ERRHRD,ERRdiskfull));
2113 outsize = set_message(outbuf,1,0,True);
2115 SSVAL(outbuf,smb_vwv0,nwritten);
2117 if (nwritten < (ssize_t)numtowrite) {
2118 SCVAL(outbuf,smb_rcls,ERRHRD);
2119 SSVAL(outbuf,smb_err,ERRdiskfull);
2122 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2124 END_PROFILE(SMBwrite);
2128 /****************************************************************************
2129 Reply to a write and X.
2130 ****************************************************************************/
2132 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2134 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2135 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2136 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2137 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2138 ssize_t nwritten = -1;
2139 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2140 unsigned int smblen = smb_len(inbuf);
2142 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2143 START_PROFILE(SMBwriteX);
2145 /* If it's an IPC, pass off the pipe handler. */
2147 END_PROFILE(SMBwriteX);
2148 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2151 CHECK_FSP(fsp,conn);
2154 /* Deal with possible LARGE_WRITEX */
2156 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2158 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2159 END_PROFILE(SMBwriteX);
2160 return ERROR_DOS(ERRDOS,ERRbadmem);
2163 data = smb_base(inbuf) + smb_doff;
2165 if(CVAL(inbuf,smb_wct) == 14) {
2166 #ifdef LARGE_SMB_OFF_T
2168 * This is a large offset (64 bit) write.
2170 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2172 #else /* !LARGE_SMB_OFF_T */
2175 * Ensure we haven't been sent a >32 bit offset.
2178 if(IVAL(inbuf,smb_vwv12) != 0) {
2179 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2180 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2181 END_PROFILE(SMBwriteX);
2182 return ERROR_DOS(ERRDOS,ERRbadaccess);
2185 #endif /* LARGE_SMB_OFF_T */
2188 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2189 END_PROFILE(SMBwriteX);
2190 return ERROR_DOS(ERRDOS,ERRlock);
2193 /* X/Open SMB protocol says that, unlike SMBwrite
2194 if the length is zero then NO truncation is
2195 done, just a write of zero. To truncate a file,
2201 nwritten = write_file(fsp,data,startpos,numtowrite);
2203 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2204 END_PROFILE(SMBwriteX);
2205 return(UNIXERROR(ERRHRD,ERRdiskfull));
2208 set_message(outbuf,6,0,True);
2210 SSVAL(outbuf,smb_vwv2,nwritten);
2212 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2214 if (nwritten < (ssize_t)numtowrite) {
2215 SCVAL(outbuf,smb_rcls,ERRHRD);
2216 SSVAL(outbuf,smb_err,ERRdiskfull);
2219 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2220 fsp->fnum, (int)numtowrite, (int)nwritten));
2222 if (lp_syncalways(SNUM(conn)) || write_through)
2223 sync_file(conn,fsp);
2225 END_PROFILE(SMBwriteX);
2226 return chain_reply(inbuf,outbuf,length,bufsize);
2229 /****************************************************************************
2231 ****************************************************************************/
2233 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2239 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2240 START_PROFILE(SMBlseek);
2242 CHECK_FSP(fsp,conn);
2244 flush_write_cache(fsp, SEEK_FLUSH);
2246 mode = SVAL(inbuf,smb_vwv1) & 3;
2247 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2248 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2265 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2267 * Check for the special case where a seek before the start
2268 * of the file sets the offset to zero. Added in the CIFS spec,
2272 if(errno == EINVAL) {
2273 SMB_OFF_T current_pos = startpos;
2275 if(umode == SEEK_CUR) {
2277 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2278 END_PROFILE(SMBlseek);
2279 return(UNIXERROR(ERRDOS,ERRnoaccess));
2282 current_pos += startpos;
2284 } else if (umode == SEEK_END) {
2286 SMB_STRUCT_STAT sbuf;
2288 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2289 END_PROFILE(SMBlseek);
2290 return(UNIXERROR(ERRDOS,ERRnoaccess));
2293 current_pos += sbuf.st_size;
2297 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2301 END_PROFILE(SMBlseek);
2302 return(UNIXERROR(ERRDOS,ERRnoaccess));
2308 outsize = set_message(outbuf,2,0,True);
2309 SIVAL(outbuf,smb_vwv0,res);
2311 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2312 fsp->fnum, (double)startpos, (double)res, mode));
2314 END_PROFILE(SMBlseek);
2318 /****************************************************************************
2320 ****************************************************************************/
2322 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2324 int outsize = set_message(outbuf,0,0,True);
2325 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2326 START_PROFILE(SMBflush);
2328 CHECK_FSP(fsp,conn);
2331 file_sync_all(conn);
2333 sync_file(conn,fsp);
2336 DEBUG(3,("flush\n"));
2337 END_PROFILE(SMBflush);
2341 /****************************************************************************
2343 ****************************************************************************/
2345 int reply_exit(connection_struct *conn,
2346 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2349 START_PROFILE(SMBexit);
2350 outsize = set_message(outbuf,0,0,True);
2352 DEBUG(3,("exit\n"));
2354 END_PROFILE(SMBexit);
2358 /****************************************************************************
2359 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2360 ****************************************************************************/
2362 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2367 int32 eclass = 0, err = 0;
2368 files_struct *fsp = NULL;
2369 START_PROFILE(SMBclose);
2371 outsize = set_message(outbuf,0,0,True);
2373 /* If it's an IPC, pass off to the pipe handler. */
2375 END_PROFILE(SMBclose);
2376 return reply_pipe_close(conn, inbuf,outbuf);
2379 fsp = file_fsp(inbuf,smb_vwv0);
2382 * We can only use CHECK_FSP if we know it's not a directory.
2385 if(!fsp || (fsp->conn != conn)) {
2386 END_PROFILE(SMBclose);
2387 return ERROR_DOS(ERRDOS,ERRbadfid);
2390 if(fsp->is_directory) {
2392 * Special case - close NT SMB directory handle.
2394 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2395 close_file(fsp,True);
2398 * Close ordinary file.
2403 /* Save the name for time set in close. */
2404 pstrcpy( file_name, fsp->fsp_name);
2406 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2408 conn->num_files_open));
2411 * close_file() returns the unix errno if an error
2412 * was detected on close - normally this is due to
2413 * a disk full error. If not then it was probably an I/O error.
2416 if((close_err = close_file(fsp,True)) != 0) {
2418 END_PROFILE(SMBclose);
2419 return (UNIXERROR(ERRHRD,ERRgeneral));
2423 * Now take care of any time sent in the close.
2426 mtime = make_unix_date3(inbuf+smb_vwv1);
2428 /* try and set the date */
2429 set_filetime(conn, file_name, mtime);
2433 /* We have a cached error */
2435 END_PROFILE(SMBclose);
2436 return ERROR_DOS(eclass,err);
2439 END_PROFILE(SMBclose);
2443 /****************************************************************************
2444 Reply to a writeclose (Core+ protocol).
2445 ****************************************************************************/
2447 int reply_writeclose(connection_struct *conn,
2448 char *inbuf,char *outbuf, int size, int dum_buffsize)
2451 ssize_t nwritten = -1;
2457 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2458 START_PROFILE(SMBwriteclose);
2460 CHECK_FSP(fsp,conn);
2463 numtowrite = SVAL(inbuf,smb_vwv1);
2464 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2465 mtime = make_unix_date3(inbuf+smb_vwv4);
2466 data = smb_buf(inbuf) + 1;
2468 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2469 END_PROFILE(SMBwriteclose);
2470 return ERROR_DOS(ERRDOS,ERRlock);
2473 nwritten = write_file(fsp,data,startpos,numtowrite);
2475 set_filetime(conn, fsp->fsp_name,mtime);
2477 close_err = close_file(fsp,True);
2479 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2480 fsp->fnum, (int)numtowrite, (int)nwritten,
2481 conn->num_files_open));
2483 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2484 END_PROFILE(SMBwriteclose);
2485 return(UNIXERROR(ERRHRD,ERRdiskfull));
2488 if(close_err != 0) {
2490 END_PROFILE(SMBwriteclose);
2491 return(UNIXERROR(ERRHRD,ERRgeneral));
2494 outsize = set_message(outbuf,1,0,True);
2496 SSVAL(outbuf,smb_vwv0,nwritten);
2497 END_PROFILE(SMBwriteclose);
2501 /****************************************************************************
2503 ****************************************************************************/
2505 int reply_lock(connection_struct *conn,
2506 char *inbuf,char *outbuf, int length, int dum_buffsize)
2508 int outsize = set_message(outbuf,0,0,True);
2509 SMB_BIG_UINT count,offset;
2511 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2512 START_PROFILE(SMBlock);
2514 CHECK_FSP(fsp,conn);
2516 release_level_2_oplocks_on_change(fsp);
2518 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2519 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2521 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2522 fsp->fd, fsp->fnum, (double)offset, (double)count));
2524 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2525 if (NT_STATUS_V(status)) {
2526 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2528 * A blocking lock was requested. Package up
2529 * this smb into a queued request and push it
2530 * onto the blocking lock queue.
2532 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2533 END_PROFILE(SMBlock);
2537 END_PROFILE(SMBlock);
2538 return ERROR_NT(status);
2541 END_PROFILE(SMBlock);
2545 /****************************************************************************
2547 ****************************************************************************/
2549 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2552 int outsize = set_message(outbuf,0,0,True);
2553 SMB_BIG_UINT count,offset;
2555 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2556 START_PROFILE(SMBunlock);
2558 CHECK_FSP(fsp,conn);
2560 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2561 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2563 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2564 if (NT_STATUS_V(status)) {
2565 END_PROFILE(SMBunlock);
2566 return ERROR_NT(status);
2569 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2570 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2572 END_PROFILE(SMBunlock);
2576 /****************************************************************************
2578 ****************************************************************************/
2580 int reply_tdis(connection_struct *conn,
2581 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2583 int outsize = set_message(outbuf,0,0,True);
2585 START_PROFILE(SMBtdis);
2587 vuid = SVAL(inbuf,smb_uid);
2590 DEBUG(4,("Invalid connection in tdis\n"));
2591 END_PROFILE(SMBtdis);
2592 return ERROR_DOS(ERRSRV,ERRinvnid);
2597 close_cnum(conn,vuid);
2599 END_PROFILE(SMBtdis);
2603 /****************************************************************************
2605 ****************************************************************************/
2607 int reply_echo(connection_struct *conn,
2608 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2610 int smb_reverb = SVAL(inbuf,smb_vwv0);
2612 unsigned int data_len = smb_buflen(inbuf);
2613 int outsize = set_message(outbuf,1,data_len,True);
2614 START_PROFILE(SMBecho);
2616 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2618 /* copy any incoming data back out */
2620 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2622 if (smb_reverb > 100) {
2623 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2627 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2628 SSVAL(outbuf,smb_vwv0,seq_num);
2630 smb_setlen(outbuf,outsize - 4);
2632 if (!send_smb(smbd_server_fd(),outbuf))
2633 exit_server("reply_echo: send_smb failed.");
2636 DEBUG(3,("echo %d times\n", smb_reverb));
2640 END_PROFILE(SMBecho);
2644 /****************************************************************************
2645 Reply to a printopen.
2646 ****************************************************************************/
2648 int reply_printopen(connection_struct *conn,
2649 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2653 START_PROFILE(SMBsplopen);
2655 if (!CAN_PRINT(conn)) {
2656 END_PROFILE(SMBsplopen);
2657 return ERROR_DOS(ERRDOS,ERRnoaccess);
2660 /* Open for exclusive use, write only. */
2661 fsp = print_fsp_open(conn, NULL);
2664 END_PROFILE(SMBsplopen);
2665 return(UNIXERROR(ERRDOS,ERRnoaccess));
2668 outsize = set_message(outbuf,1,0,True);
2669 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2671 DEBUG(3,("openprint fd=%d fnum=%d\n",
2672 fsp->fd, fsp->fnum));
2674 END_PROFILE(SMBsplopen);
2678 /****************************************************************************
2679 Reply to a printclose.
2680 ****************************************************************************/
2682 int reply_printclose(connection_struct *conn,
2683 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2685 int outsize = set_message(outbuf,0,0,True);
2686 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2688 START_PROFILE(SMBsplclose);
2690 CHECK_FSP(fsp,conn);
2692 if (!CAN_PRINT(conn)) {
2693 END_PROFILE(SMBsplclose);
2694 return ERROR_DOS(ERRDOS,ERRnoaccess);
2697 DEBUG(3,("printclose fd=%d fnum=%d\n",
2698 fsp->fd,fsp->fnum));
2700 close_err = close_file(fsp,True);
2702 if(close_err != 0) {
2704 END_PROFILE(SMBsplclose);
2705 return(UNIXERROR(ERRHRD,ERRgeneral));
2708 END_PROFILE(SMBsplclose);
2712 /****************************************************************************
2713 Reply to a printqueue.
2714 ****************************************************************************/
2716 int reply_printqueue(connection_struct *conn,
2717 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2719 int outsize = set_message(outbuf,2,3,True);
2720 int max_count = SVAL(inbuf,smb_vwv0);
2721 int start_index = SVAL(inbuf,smb_vwv1);
2722 START_PROFILE(SMBsplretq);
2724 /* we used to allow the client to get the cnum wrong, but that
2725 is really quite gross and only worked when there was only
2726 one printer - I think we should now only accept it if they
2727 get it right (tridge) */
2728 if (!CAN_PRINT(conn)) {
2729 END_PROFILE(SMBsplretq);
2730 return ERROR_DOS(ERRDOS,ERRnoaccess);
2733 SSVAL(outbuf,smb_vwv0,0);
2734 SSVAL(outbuf,smb_vwv1,0);
2735 SCVAL(smb_buf(outbuf),0,1);
2736 SSVAL(smb_buf(outbuf),1,0);
2738 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2739 start_index, max_count));
2742 print_queue_struct *queue = NULL;
2743 print_status_struct status;
2744 char *p = smb_buf(outbuf) + 3;
2745 int count = print_queue_status(SNUM(conn), &queue, &status);
2746 int num_to_get = ABS(max_count);
2747 int first = (max_count>0?start_index:start_index+max_count+1);
2753 num_to_get = MIN(num_to_get,count-first);
2756 for (i=first;i<first+num_to_get;i++) {
2757 put_dos_date2(p,0,queue[i].time);
2758 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2759 SSVAL(p,5, queue[i].job);
2760 SIVAL(p,7,queue[i].size);
2762 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2767 outsize = set_message(outbuf,2,28*count+3,False);
2768 SSVAL(outbuf,smb_vwv0,count);
2769 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2770 SCVAL(smb_buf(outbuf),0,1);
2771 SSVAL(smb_buf(outbuf),1,28*count);
2776 DEBUG(3,("%d entries returned in queue\n",count));
2779 END_PROFILE(SMBsplretq);
2783 /****************************************************************************
2784 Reply to a printwrite.
2785 ****************************************************************************/
2787 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2790 int outsize = set_message(outbuf,0,0,True);
2792 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2794 START_PROFILE(SMBsplwr);
2796 if (!CAN_PRINT(conn)) {
2797 END_PROFILE(SMBsplwr);
2798 return ERROR_DOS(ERRDOS,ERRnoaccess);
2801 CHECK_FSP(fsp,conn);
2804 numtowrite = SVAL(smb_buf(inbuf),1);
2805 data = smb_buf(inbuf) + 3;
2807 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2808 END_PROFILE(SMBsplwr);
2809 return(UNIXERROR(ERRHRD,ERRdiskfull));
2812 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2814 END_PROFILE(SMBsplwr);
2818 /****************************************************************************
2819 The guts of the mkdir command, split out so it may be called by the NT SMB
2821 ****************************************************************************/
2823 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2825 BOOL bad_path = False;
2826 SMB_STRUCT_STAT sbuf;
2829 unix_convert(directory,conn,0,&bad_path,&sbuf);
2831 if (check_name(directory, conn))
2832 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2835 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2836 if (!NT_STATUS_IS_OK(nterr))
2838 return map_nt_error_from_unix(errno);
2841 return NT_STATUS_OK;
2844 /****************************************************************************
2846 ****************************************************************************/
2848 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2853 START_PROFILE(SMBmkdir);
2855 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2857 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2859 status = mkdir_internal(conn, directory);
2860 if (!NT_STATUS_IS_OK(status))
2861 return ERROR_NT(status);
2863 outsize = set_message(outbuf,0,0,True);
2865 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2867 END_PROFILE(SMBmkdir);
2871 /****************************************************************************
2872 Static function used by reply_rmdir to delete an entire directory
2873 tree recursively. Return False on ok, True on fail.
2874 ****************************************************************************/
2876 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2878 const char *dname = NULL;
2880 void *dirptr = OpenDir(conn, directory, False);
2885 while((dname = ReadDirName(dirptr))) {
2889 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2892 /* Construct the full name. */
2893 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2899 pstrcpy(fullname, directory);
2900 pstrcat(fullname, "/");
2901 pstrcat(fullname, dname);
2903 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2908 if(st.st_mode & S_IFDIR) {
2909 if(recursive_rmdir(conn, fullname)!=0) {
2913 if(vfs_rmdir(conn,fullname) != 0) {
2917 } else if(vfs_unlink(conn,fullname) != 0) {
2926 /****************************************************************************
2927 The internals of the rmdir code - called elsewhere.
2928 ****************************************************************************/
2930 BOOL rmdir_internals(connection_struct *conn, char *directory)
2934 ok = (vfs_rmdir(conn,directory) == 0);
2935 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2937 * Check to see if the only thing in this directory are
2938 * vetoed files/directories. If so then delete them and
2939 * retry. If we fail to delete any of them (and we *don't*
2940 * do a recursive delete) then fail the rmdir.
2942 BOOL all_veto_files = True;
2944 void *dirptr = OpenDir(conn, directory, False);
2946 if(dirptr != NULL) {
2947 int dirpos = TellDir(dirptr);
2948 while ((dname = ReadDirName(dirptr))) {
2949 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2951 if(!IS_VETO_PATH(conn, dname)) {
2952 all_veto_files = False;
2957 if(all_veto_files) {
2958 SeekDir(dirptr,dirpos);
2959 while ((dname = ReadDirName(dirptr))) {
2963 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2966 /* Construct the full name. */
2967 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2972 pstrcpy(fullname, directory);
2973 pstrcat(fullname, "/");
2974 pstrcat(fullname, dname);
2976 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2978 if(st.st_mode & S_IFDIR) {
2979 if(lp_recursive_veto_delete(SNUM(conn))) {
2980 if(recursive_rmdir(conn, fullname) != 0)
2983 if(vfs_rmdir(conn,fullname) != 0)
2985 } else if(vfs_unlink(conn,fullname) != 0)
2989 /* Retry the rmdir */
2990 ok = (vfs_rmdir(conn,directory) == 0);
3000 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3005 /****************************************************************************
3007 ****************************************************************************/
3009 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3014 BOOL bad_path = False;
3015 SMB_STRUCT_STAT sbuf;
3016 START_PROFILE(SMBrmdir);
3018 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3020 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3022 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3024 if (check_name(directory,conn)) {
3025 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3026 ok = rmdir_internals(conn, directory);
3030 set_bad_path_error(errno, bad_path);
3031 END_PROFILE(SMBrmdir);
3032 return(UNIXERROR(ERRDOS,ERRbadpath));
3035 outsize = set_message(outbuf,0,0,True);
3037 DEBUG( 3, ( "rmdir %s\n", directory ) );
3039 END_PROFILE(SMBrmdir);
3043 /*******************************************************************
3044 Resolve wildcards in a filename rename.
3045 ********************************************************************/
3047 static BOOL resolve_wildcards(char *name1,char *name2)
3049 fstring root1,root2;
3053 name1 = strrchr_m(name1,'/');
3054 name2 = strrchr_m(name2,'/');
3056 if (!name1 || !name2)
3059 fstrcpy(root1,name1);
3060 fstrcpy(root2,name2);
3061 p = strrchr_m(root1,'.');
3068 p = strrchr_m(root2,'.');
3102 pstrcpy(name2,root2);
3105 pstrcat(name2,ext2);
3111 /****************************************************************************
3112 The guts of the rename command, split out so it may be called by the NT SMB
3114 ****************************************************************************/
3116 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3120 pstring newname_last_component;
3123 BOOL bad_path1 = False;
3124 BOOL bad_path2 = False;
3126 NTSTATUS error = NT_STATUS_OK;
3128 SMB_STRUCT_STAT sbuf1, sbuf2;
3130 *directory = *mask = 0;
3132 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3133 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3136 * Split the old name into directory and last component
3137 * strings. Note that unix_convert may have stripped off a
3138 * leading ./ from both name and newname if the rename is
3139 * at the root of the share. We need to make sure either both
3140 * name and newname contain a / character or neither of them do
3141 * as this is checked in resolve_wildcards().
3144 p = strrchr_m(name,'/');
3146 pstrcpy(directory,".");
3150 pstrcpy(directory,name);
3152 *p = '/'; /* Replace needed for exceptional test below. */
3156 * We should only check the mangled cache
3157 * here if unix_convert failed. This means
3158 * that the path in 'mask' doesn't exist
3159 * on the file system and so we need to look
3160 * for a possible mangle. This patch from
3161 * Tine Smukavec <valentin.smukavec@hermes.si>.
3164 if (!rc && mangle_is_mangled(mask))
3165 mangle_check_cache( mask );
3167 has_wild = ms_has_wild(mask);
3171 * No wildcards - just process the one file.
3173 BOOL is_short_name = mangle_is_8_3(name, True);
3175 /* Add a terminating '/' to the directory name. */
3176 pstrcat(directory,"/");
3177 pstrcat(directory,mask);
3179 /* Ensure newname contains a '/' also */
3180 if(strrchr_m(newname,'/') == 0) {
3183 pstrcpy(tmpstr, "./");
3184 pstrcat(tmpstr, newname);
3185 pstrcpy(newname, tmpstr);
3188 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3189 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3190 case_sensitive, case_preserve, short_case_preserve, directory,
3191 newname, newname_last_component, is_short_name));
3194 * Check for special case with case preserving and not
3195 * case sensitive, if directory and newname are identical,
3196 * and the old last component differs from the original
3197 * last component only by case, then we should allow
3198 * the rename (user is trying to change the case of the
3201 if((case_sensitive == False) &&
3202 (((case_preserve == True) &&
3203 (is_short_name == False)) ||
3204 ((short_case_preserve == True) &&
3205 (is_short_name == True))) &&
3206 strcsequal(directory, newname)) {
3207 pstring newname_modified_last_component;
3210 * Get the last component of the modified name.
3211 * Note that we guarantee that newname contains a '/'
3214 p = strrchr_m(newname,'/');
3215 pstrcpy(newname_modified_last_component,p+1);
3217 if(strcsequal(newname_modified_last_component,
3218 newname_last_component) == False) {
3220 * Replace the modified last component with
3223 pstrcpy(p+1, newname_last_component);
3227 resolve_wildcards(directory,newname);
3230 * The source object must exist.
3233 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3234 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3235 directory,newname));
3237 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3239 * Must return different errors depending on whether the parent
3240 * directory existed or not.
3243 p = strrchr_m(directory, '/');
3245 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3247 if (vfs_object_exist(conn, directory, NULL))
3248 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3249 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3251 error = map_nt_error_from_unix(errno);
3252 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3253 nt_errstr(error), directory,newname));
3258 error = can_rename(directory,conn,&sbuf1);
3260 if (!NT_STATUS_IS_OK(error)) {
3261 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3262 nt_errstr(error), directory,newname));
3267 * If the src and dest names are identical - including case,
3268 * don't do the rename, just return success.
3271 if (strcsequal(directory, newname)) {
3272 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3273 return NT_STATUS_OK;
3276 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3277 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3278 directory,newname));
3279 return NT_STATUS_OBJECT_NAME_COLLISION;
3282 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3283 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3284 directory,newname));
3285 return NT_STATUS_OK;
3288 if (errno == ENOTDIR || errno == EISDIR)
3289 error = NT_STATUS_OBJECT_NAME_COLLISION;
3291 error = map_nt_error_from_unix(errno);
3293 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3294 nt_errstr(error), directory,newname));
3299 * Wildcards - process each file that matches.
3301 void *dirptr = NULL;
3305 if (check_name(directory,conn))
3306 dirptr = OpenDir(conn, directory, True);
3309 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3311 if (strequal(mask,"????????.???"))
3314 while ((dname = ReadDirName(dirptr))) {
3317 pstrcpy(fname,dname);
3319 if(!mask_match(fname, mask, case_sensitive))
3322 error = NT_STATUS_ACCESS_DENIED;
3323 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3324 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3325 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3326 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3329 error = can_rename(fname,conn,&sbuf1);
3330 if (!NT_STATUS_IS_OK(error)) {
3331 DEBUG(6,("rename %s refused\n", fname));
3334 pstrcpy(destname,newname);
3336 if (!resolve_wildcards(fname,destname)) {
3337 DEBUG(6,("resolve_wildcards %s %s failed\n",
3342 if (!replace_if_exists &&
3343 vfs_file_exist(conn,destname, NULL)) {
3344 DEBUG(6,("file_exist %s\n", destname));
3345 error = NT_STATUS_OBJECT_NAME_COLLISION;
3349 if (!conn->vfs_ops.rename(conn,fname,destname))
3351 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3357 if (count == 0 && NT_STATUS_IS_OK(error)) {
3358 error = map_nt_error_from_unix(errno);
3364 /****************************************************************************
3366 ****************************************************************************/
3368 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3377 START_PROFILE(SMBmv);
3379 p = smb_buf(inbuf) + 1;
3380 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3382 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3384 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3385 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3387 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3389 status = rename_internals(conn, name, newname, False);
3390 if (!NT_STATUS_IS_OK(status)) {
3391 return ERROR_NT(status);
3395 * Win2k needs a changenotify request response before it will
3396 * update after a rename..
3398 process_pending_change_notify_queue((time_t)0);
3399 outsize = set_message(outbuf,0,0,True);
3405 /*******************************************************************
3406 Copy a file as part of a reply_copy.
3407 ******************************************************************/
3409 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3410 int count,BOOL target_is_directory, int *err_ret)
3413 SMB_STRUCT_STAT src_sbuf, sbuf2;
3415 files_struct *fsp1,*fsp2;
3420 pstrcpy(dest,dest1);
3421 if (target_is_directory) {
3422 char *p = strrchr_m(src,'/');
3431 if (!vfs_file_exist(conn,src,&src_sbuf))
3434 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3435 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3440 if (!target_is_directory && count)
3441 ofun = FILE_EXISTS_OPEN;
3443 if (vfs_stat(conn,dest,&sbuf2) == -1)
3444 ZERO_STRUCTP(&sbuf2);
3446 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3447 ofun,src_sbuf.st_mode,0,&Access,&action);
3450 close_file(fsp1,False);
3454 if ((ofun&3) == 1) {
3455 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3456 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3458 * Stop the copy from occurring.
3461 src_sbuf.st_size = 0;
3465 if (src_sbuf.st_size)
3466 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3468 close_file(fsp1,False);
3470 /* Ensure the modtime is set correctly on the destination file. */
3471 fsp2->pending_modtime = src_sbuf.st_mtime;
3474 * As we are opening fsp1 read-only we only expect
3475 * an error on close on fsp2 if we are out of space.
3476 * Thus we don't look at the error return from the
3479 *err_ret = close_file(fsp2,False);
3481 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3484 /****************************************************************************
3485 Reply to a file copy.
3486 ****************************************************************************/
3488 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3493 pstring mask,newname;
3496 int error = ERRnoaccess;
3500 int tid2 = SVAL(inbuf,smb_vwv0);
3501 int ofun = SVAL(inbuf,smb_vwv1);
3502 int flags = SVAL(inbuf,smb_vwv2);
3503 BOOL target_is_directory=False;
3504 BOOL bad_path1 = False;
3505 BOOL bad_path2 = False;
3507 SMB_STRUCT_STAT sbuf1, sbuf2;
3509 START_PROFILE(SMBcopy);
3511 *directory = *mask = 0;
3514 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3515 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3517 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3519 if (tid2 != conn->cnum) {
3520 /* can't currently handle inter share copies XXXX */
3521 DEBUG(3,("Rejecting inter-share copy\n"));
3522 END_PROFILE(SMBcopy);
3523 return ERROR_DOS(ERRSRV,ERRinvdevice);
3526 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3527 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3529 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3530 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3532 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3534 if ((flags&1) && target_is_directory) {
3535 END_PROFILE(SMBcopy);
3536 return ERROR_DOS(ERRDOS,ERRbadfile);
3539 if ((flags&2) && !target_is_directory) {
3540 END_PROFILE(SMBcopy);
3541 return ERROR_DOS(ERRDOS,ERRbadpath);
3544 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3545 /* wants a tree copy! XXXX */
3546 DEBUG(3,("Rejecting tree copy\n"));
3547 END_PROFILE(SMBcopy);
3548 return ERROR_DOS(ERRSRV,ERRerror);
3551 p = strrchr_m(name,'/');
3553 pstrcpy(directory,"./");
3557 pstrcpy(directory,name);
3562 * We should only check the mangled cache
3563 * here if unix_convert failed. This means
3564 * that the path in 'mask' doesn't exist
3565 * on the file system and so we need to look
3566 * for a possible mangle. This patch from
3567 * Tine Smukavec <valentin.smukavec@hermes.si>.
3570 if (!rc && mangle_is_mangled(mask))
3571 mangle_check_cache( mask );
3573 has_wild = ms_has_wild(mask);
3576 pstrcat(directory,"/");
3577 pstrcat(directory,mask);
3578 if (resolve_wildcards(directory,newname) &&
3579 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3583 END_PROFILE(SMBcopy);
3584 return(UNIXERROR(ERRHRD,ERRgeneral));
3587 exists = vfs_file_exist(conn,directory,NULL);
3590 void *dirptr = NULL;
3594 if (check_name(directory,conn))
3595 dirptr = OpenDir(conn, directory, True);
3600 if (strequal(mask,"????????.???"))
3603 while ((dname = ReadDirName(dirptr))) {
3605 pstrcpy(fname,dname);
3607 if(!mask_match(fname, mask, case_sensitive))
3610 error = ERRnoaccess;
3611 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3612 pstrcpy(destname,newname);
3613 if (resolve_wildcards(fname,destname) &&
3614 copy_file(fname,destname,conn,ofun,
3615 count,target_is_directory,&err))
3617 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3625 /* Error on close... */
3627 END_PROFILE(SMBcopy);
3628 return(UNIXERROR(ERRHRD,ERRgeneral));
3632 END_PROFILE(SMBcopy);
3633 return ERROR_DOS(ERRDOS,error);
3635 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3636 unix_ERR_class = ERRDOS;
3637 unix_ERR_code = ERRbadpath;
3639 END_PROFILE(SMBcopy);
3640 return(UNIXERROR(ERRDOS,error));
3644 outsize = set_message(outbuf,1,0,True);
3645 SSVAL(outbuf,smb_vwv0,count);
3647 END_PROFILE(SMBcopy);
3651 /****************************************************************************
3653 ****************************************************************************/
3655 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3662 START_PROFILE(pathworks_setdir);
3665 if (!CAN_SETDIR(snum)) {
3666 END_PROFILE(pathworks_setdir);
3667 return ERROR_DOS(ERRDOS,ERRnoaccess);
3670 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3672 if (strlen(newdir) == 0) {
3675 ok = vfs_directory_exist(conn,newdir,NULL);
3677 string_set(&conn->connectpath,newdir);
3681 END_PROFILE(pathworks_setdir);
3682 return ERROR_DOS(ERRDOS,ERRbadpath);
3685 outsize = set_message(outbuf,0,0,True);
3686 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3688 DEBUG(3,("setdir %s\n", newdir));
3690 END_PROFILE(pathworks_setdir);
3694 /****************************************************************************
3695 Get a lock pid, dealing with large count requests.
3696 ****************************************************************************/
3698 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3700 if(!large_file_format)
3701 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3703 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3706 /****************************************************************************
3707 Get a lock count, dealing with large count requests.
3708 ****************************************************************************/
3710 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3712 SMB_BIG_UINT count = 0;
3714 if(!large_file_format) {
3715 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3718 #if defined(HAVE_LONGLONG)
3719 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3720 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3721 #else /* HAVE_LONGLONG */
3724 * NT4.x seems to be broken in that it sends large file (64 bit)
3725 * lockingX calls even if the CAP_LARGE_FILES was *not*
3726 * negotiated. For boxes without large unsigned ints truncate the
3727 * lock count by dropping the top 32 bits.
3730 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3731 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3732 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3733 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3734 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3737 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3738 #endif /* HAVE_LONGLONG */
3744 #if !defined(HAVE_LONGLONG)
3745 /****************************************************************************
3746 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3747 ****************************************************************************/
3749 static uint32 map_lock_offset(uint32 high, uint32 low)
3753 uint32 highcopy = high;
3756 * Try and find out how many significant bits there are in high.
3759 for(i = 0; highcopy; i++)
3763 * We use 31 bits not 32 here as POSIX
3764 * lock offsets may not be negative.
3767 mask = (~0) << (31 - i);
3770 return 0; /* Fail. */
3776 #endif /* !defined(HAVE_LONGLONG) */
3778 /****************************************************************************
3779 Get a lock offset, dealing with large offset requests.
3780 ****************************************************************************/
3782 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3784 SMB_BIG_UINT offset = 0;
3788 if(!large_file_format) {
3789 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3792 #if defined(HAVE_LONGLONG)
3793 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3794 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3795 #else /* HAVE_LONGLONG */
3798 * NT4.x seems to be broken in that it sends large file (64 bit)
3799 * lockingX calls even if the CAP_LARGE_FILES was *not*
3800 * negotiated. For boxes without large unsigned ints mangle the
3801 * lock offset by mapping the top 32 bits onto the lower 32.
3804 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3805 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3806 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3809 if((new_low = map_lock_offset(high, low)) == 0) {
3811 return (SMB_BIG_UINT)-1;
3814 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3815 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3816 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3817 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3820 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3821 #endif /* HAVE_LONGLONG */
3827 /****************************************************************************
3828 Reply to a lockingX request.
3829 ****************************************************************************/
3831 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3833 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3834 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3835 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3836 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3837 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3838 SMB_BIG_UINT count = 0, offset = 0;
3840 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3843 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3847 START_PROFILE(SMBlockingX);
3849 CHECK_FSP(fsp,conn);
3851 data = smb_buf(inbuf);
3853 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3854 /* we don't support these - and CANCEL_LOCK makes w2k
3855 and XP reboot so I don't really want to be
3856 compatible! (tridge) */
3857 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3860 /* Check if this is an oplock break on a file
3861 we have granted an oplock on.
3863 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3864 /* Client can insist on breaking to none. */
3865 BOOL break_to_none = (oplocklevel == 0);
3867 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3868 (unsigned int)oplocklevel, fsp->fnum ));
3871 * Make sure we have granted an exclusive or batch oplock on this file.
3874 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3875 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3876 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3878 /* if this is a pure oplock break request then don't send a reply */
3879 if (num_locks == 0 && num_ulocks == 0) {
3880 END_PROFILE(SMBlockingX);
3883 END_PROFILE(SMBlockingX);
3884 return ERROR_DOS(ERRDOS,ERRlock);
3888 if (remove_oplock(fsp, break_to_none) == False) {
3889 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3893 /* if this is a pure oplock break request then don't send a reply */
3894 if (num_locks == 0 && num_ulocks == 0) {
3895 /* Sanity check - ensure a pure oplock break is not a
3897 if(CVAL(inbuf,smb_vwv0) != 0xff)
3898 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3899 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3900 END_PROFILE(SMBlockingX);
3906 * We do this check *after* we have checked this is not a oplock break
3907 * response message. JRA.
3910 release_level_2_oplocks_on_change(fsp);
3912 /* Data now points at the beginning of the list
3913 of smb_unlkrng structs */
3914 for(i = 0; i < (int)num_ulocks; i++) {
3915 lock_pid = get_lock_pid( data, i, large_file_format);
3916 count = get_lock_count( data, i, large_file_format);
3917 offset = get_lock_offset( data, i, large_file_format, &err);
3920 * There is no error code marked "stupid client bug".... :-).
3923 END_PROFILE(SMBlockingX);
3924 return ERROR_DOS(ERRDOS,ERRnoaccess);
3927 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3928 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3930 status = do_unlock(fsp,conn,lock_pid,count,offset);
3931 if (NT_STATUS_V(status)) {
3932 END_PROFILE(SMBlockingX);
3933 return ERROR_NT(status);
3937 /* Setup the timeout in seconds. */
3939 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3941 /* Now do any requested locks */
3942 data += ((large_file_format ? 20 : 10)*num_ulocks);
3944 /* Data now points at the beginning of the list
3945 of smb_lkrng structs */
3947 for(i = 0; i < (int)num_locks; i++) {
3948 lock_pid = get_lock_pid( data, i, large_file_format);
3949 count = get_lock_count( data, i, large_file_format);
3950 offset = get_lock_offset( data, i, large_file_format, &err);
3953 * There is no error code marked "stupid client bug".... :-).
3956 END_PROFILE(SMBlockingX);
3957 return ERROR_DOS(ERRDOS,ERRnoaccess);
3960 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3961 (double)offset, (double)count, (unsigned int)lock_pid,
3962 fsp->fsp_name, (int)lock_timeout ));
3964 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3965 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3966 if (NT_STATUS_V(status)) {
3967 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3969 * A blocking lock was requested. Package up
3970 * this smb into a queued request and push it
3971 * onto the blocking lock queue.
3973 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
3974 END_PROFILE(SMBlockingX);
3982 /* If any of the above locks failed, then we must unlock
3983 all of the previous locks (X/Open spec). */
3984 if (i != num_locks && num_locks != 0) {
3986 * Ensure we don't do a remove on the lock that just failed,
3987 * as under POSIX rules, if we have a lock already there, we
3988 * will delete it (and we shouldn't) .....
3990 for(i--; i >= 0; i--) {
3991 lock_pid = get_lock_pid( data, i, large_file_format);
3992 count = get_lock_count( data, i, large_file_format);
3993 offset = get_lock_offset( data, i, large_file_format, &err);
3996 * There is no error code marked "stupid client bug".... :-).
3999 END_PROFILE(SMBlockingX);
4000 return ERROR_DOS(ERRDOS,ERRnoaccess);
4003 do_unlock(fsp,conn,lock_pid,count,offset);
4005 END_PROFILE(SMBlockingX);
4006 return ERROR_NT(status);
4009 set_message(outbuf,2,0,True);
4011 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4012 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4014 END_PROFILE(SMBlockingX);
4015 return chain_reply(inbuf,outbuf,length,bufsize);
4018 /****************************************************************************
4019 Reply to a SMBreadbmpx (read block multiplex) request.
4020 ****************************************************************************/
4022 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4033 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4034 START_PROFILE(SMBreadBmpx);
4036 /* this function doesn't seem to work - disable by default */
4037 if (!lp_readbmpx()) {
4038 END_PROFILE(SMBreadBmpx);
4039 return ERROR_DOS(ERRSRV,ERRuseSTD);
4042 outsize = set_message(outbuf,8,0,True);
4044 CHECK_FSP(fsp,conn);
4047 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4048 maxcount = SVAL(inbuf,smb_vwv3);
4050 data = smb_buf(outbuf);
4051 pad = ((long)data)%4;
4056 max_per_packet = bufsize-(outsize+pad);
4060 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4061 END_PROFILE(SMBreadBmpx);
4062 return ERROR_DOS(ERRDOS,ERRlock);
4066 size_t N = MIN(max_per_packet,tcount-total_read);
4068 nread = read_file(fsp,data,startpos,N);
4073 if (nread < (ssize_t)N)
4074 tcount = total_read + nread;
4076 set_message(outbuf,8,nread,False);
4077 SIVAL(outbuf,smb_vwv0,startpos);
4078 SSVAL(outbuf,smb_vwv2,tcount);
4079 SSVAL(outbuf,smb_vwv6,nread);
4080 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4082 if (!send_smb(smbd_server_fd(),outbuf))
4083 exit_server("reply_readbmpx: send_smb failed.");
4085 total_read += nread;
4087 } while (total_read < (ssize_t)tcount);
4089 END_PROFILE(SMBreadBmpx);
4093 /****************************************************************************
4094 Reply to a SMBsetattrE.
4095 ****************************************************************************/
4097 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4099 struct utimbuf unix_times;
4101 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4102 START_PROFILE(SMBsetattrE);
4104 outsize = set_message(outbuf,0,0,True);
4106 if(!fsp || (fsp->conn != conn)) {
4107 END_PROFILE(SMBgetattrE);
4108 return ERROR_DOS(ERRDOS,ERRbadfid);
4112 * Convert the DOS times into unix times. Ignore create
4113 * time as UNIX can't set this.
4116 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4117 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4120 * Patch from Ray Frush <frush@engr.colostate.edu>
4121 * Sometimes times are sent as zero - ignore them.
4124 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4125 /* Ignore request */
4126 if( DEBUGLVL( 3 ) ) {
4127 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4128 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4130 END_PROFILE(SMBsetattrE);
4132 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4133 /* set modify time = to access time if modify time was 0 */
4134 unix_times.modtime = unix_times.actime;
4137 /* Set the date on this file */
4138 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4139 END_PROFILE(SMBsetattrE);
4140 return ERROR_DOS(ERRDOS,ERRnoaccess);
4143 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4144 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4146 END_PROFILE(SMBsetattrE);
4151 /* Back from the dead for OS/2..... JRA. */
4153 /****************************************************************************
4154 Reply to a SMBwritebmpx (write block multiplex primary) request.
4155 ****************************************************************************/
4157 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4160 ssize_t nwritten = -1;
4167 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4168 START_PROFILE(SMBwriteBmpx);
4170 CHECK_FSP(fsp,conn);
4174 tcount = SVAL(inbuf,smb_vwv1);
4175 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4176 write_through = BITSETW(inbuf+smb_vwv7,0);
4177 numtowrite = SVAL(inbuf,smb_vwv10);
4178 smb_doff = SVAL(inbuf,smb_vwv11);
4180 data = smb_base(inbuf) + smb_doff;
4182 /* If this fails we need to send an SMBwriteC response,
4183 not an SMBwritebmpx - set this up now so we don't forget */
4184 SCVAL(outbuf,smb_com,SMBwritec);
4186 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4187 END_PROFILE(SMBwriteBmpx);
4188 return(ERROR_DOS(ERRDOS,ERRlock));
4191 nwritten = write_file(fsp,data,startpos,numtowrite);
4193 if(lp_syncalways(SNUM(conn)) || write_through)
4194 sync_file(conn,fsp);
4196 if(nwritten < (ssize_t)numtowrite) {
4197 END_PROFILE(SMBwriteBmpx);
4198 return(UNIXERROR(ERRHRD,ERRdiskfull));
4201 /* If the maximum to be written to this file
4202 is greater than what we just wrote then set
4203 up a secondary struct to be attached to this
4204 fd, we will use this to cache error messages etc. */
4206 if((ssize_t)tcount > nwritten) {
4207 write_bmpx_struct *wbms;
4208 if(fsp->wbmpx_ptr != NULL)
4209 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4211 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4213 DEBUG(0,("Out of memory in reply_readmpx\n"));
4214 END_PROFILE(SMBwriteBmpx);
4215 return(ERROR_DOS(ERRSRV,ERRnoresource));
4217 wbms->wr_mode = write_through;
4218 wbms->wr_discard = False; /* No errors yet */
4219 wbms->wr_total_written = nwritten;
4220 wbms->wr_errclass = 0;
4222 fsp->wbmpx_ptr = wbms;
4225 /* We are returning successfully, set the message type back to
4227 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4229 outsize = set_message(outbuf,1,0,True);
4231 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4233 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4234 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4236 if (write_through && tcount==nwritten) {
4237 /* We need to send both a primary and a secondary response */
4238 smb_setlen(outbuf,outsize - 4);
4239 if (!send_smb(smbd_server_fd(),outbuf))
4240 exit_server("reply_writebmpx: send_smb failed.");
4242 /* Now the secondary */
4243 outsize = set_message(outbuf,1,0,True);
4244 SCVAL(outbuf,smb_com,SMBwritec);
4245 SSVAL(outbuf,smb_vwv0,nwritten);
4248 END_PROFILE(SMBwriteBmpx);
4252 /****************************************************************************
4253 Reply to a SMBwritebs (write block multiplex secondary) request.
4254 ****************************************************************************/
4256 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4259 ssize_t nwritten = -1;
4266 write_bmpx_struct *wbms;
4267 BOOL send_response = False;
4268 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4269 START_PROFILE(SMBwriteBs);
4271 CHECK_FSP(fsp,conn);
4274 tcount = SVAL(inbuf,smb_vwv1);
4275 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4276 numtowrite = SVAL(inbuf,smb_vwv6);
4277 smb_doff = SVAL(inbuf,smb_vwv7);
4279 data = smb_base(inbuf) + smb_doff;
4281 /* We need to send an SMBwriteC response, not an SMBwritebs */
4282 SCVAL(outbuf,smb_com,SMBwritec);
4284 /* This fd should have an auxiliary struct attached,
4285 check that it does */
4286 wbms = fsp->wbmpx_ptr;
4288 END_PROFILE(SMBwriteBs);
4292 /* If write through is set we can return errors, else we must cache them */
4293 write_through = wbms->wr_mode;
4295 /* Check for an earlier error */
4296 if(wbms->wr_discard) {
4297 END_PROFILE(SMBwriteBs);
4298 return -1; /* Just discard the packet */
4301 nwritten = write_file(fsp,data,startpos,numtowrite);
4303 if(lp_syncalways(SNUM(conn)) || write_through)
4304 sync_file(conn,fsp);
4306 if (nwritten < (ssize_t)numtowrite) {
4308 /* We are returning an error - we can delete the aux struct */
4311 fsp->wbmpx_ptr = NULL;
4312 END_PROFILE(SMBwriteBs);
4313 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4315 END_PROFILE(SMBwriteBs);
4316 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4319 /* Increment the total written, if this matches tcount
4320 we can discard the auxiliary struct (hurrah !) and return a writeC */
4321 wbms->wr_total_written += nwritten;
4322 if(wbms->wr_total_written >= tcount) {
4323 if (write_through) {
4324 outsize = set_message(outbuf,1,0,True);
4325 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4326 send_response = True;
4330 fsp->wbmpx_ptr = NULL;
4334 END_PROFILE(SMBwriteBs);
4338 END_PROFILE(SMBwriteBs);
4342 /****************************************************************************
4343 Reply to a SMBgetattrE.
4344 ****************************************************************************/
4346 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4348 SMB_STRUCT_STAT sbuf;
4351 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4352 START_PROFILE(SMBgetattrE);
4354 outsize = set_message(outbuf,11,0,True);
4356 if(!fsp || (fsp->conn != conn)) {
4357 END_PROFILE(SMBgetattrE);
4358 return ERROR_DOS(ERRDOS,ERRbadfid);
4361 /* Do an fstat on this file */
4362 if(fsp_stat(fsp, &sbuf)) {
4363 END_PROFILE(SMBgetattrE);
4364 return(UNIXERROR(ERRDOS,ERRnoaccess));
4367 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4370 * Convert the times into dos times. Set create
4371 * date to be last modify date as UNIX doesn't save
4375 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4376 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4377 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4380 SIVAL(outbuf,smb_vwv6,0);
4381 SIVAL(outbuf,smb_vwv8,0);
4383 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4384 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4386 SSVAL(outbuf,smb_vwv10, mode);
4388 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4390 END_PROFILE(SMBgetattrE);