2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Ensure we check the path in the same way as W2K.
43 ****************************************************************************/
45 static NTSTATUS check_path_syntax(const char *name)
49 if (strequal(name, "."))
50 return NT_STATUS_OBJECT_NAME_INVALID;
51 else if (strequal(name, ".."))
52 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
56 /****************************************************************************
57 Reply to a special message.
58 ****************************************************************************/
60 int reply_special(char *inbuf,char *outbuf)
63 int msg_type = CVAL(inbuf,0);
64 int msg_flags = CVAL(inbuf,1);
68 static BOOL already_got_session = False;
72 memset(outbuf,'\0',smb_size);
77 case 0x81: /* session request */
79 if (already_got_session) {
80 exit_server("multiple session request not permitted");
85 if (name_len(inbuf+4) > 50 ||
86 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
90 name_extract(inbuf,4,name1);
91 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 set_local_machine_name(name1, True);
96 set_remote_machine_name(name2, True);
98 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
99 get_local_machine_name(), get_remote_machine_name(),
102 if (name_type == 'R') {
103 /* We are being asked for a pathworks session ---
105 SCVAL(outbuf, 0,0x83);
109 /* only add the client's machine name to the list
110 of possibly valid usernames if we are operating
111 in share mode security */
112 if (lp_security() == SEC_SHARE) {
113 add_session_user(get_remote_machine_name());
116 reload_services(True);
119 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
121 already_got_session = True;
124 case 0x89: /* session keepalive request
125 (some old clients produce this?) */
126 SCVAL(outbuf,0,SMBkeepalive);
130 case 0x82: /* positive session response */
131 case 0x83: /* negative session response */
132 case 0x84: /* retarget session response */
133 DEBUG(0,("Unexpected session response\n"));
136 case SMBkeepalive: /* session keepalive */
141 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
142 msg_type, msg_flags));
147 /****************************************************************************
149 ****************************************************************************/
151 int reply_tcon(connection_struct *conn,
152 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
159 uint16 vuid = SVAL(inbuf,smb_uid);
163 DATA_BLOB password_blob;
165 START_PROFILE(SMBtcon);
167 *service_buf = *password = *dev = 0;
169 p = smb_buf(inbuf)+1;
170 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
171 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
173 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
175 p = strrchr_m(service_buf,'\\');
179 service = service_buf;
182 password_blob = data_blob(password, pwlen+1);
184 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
186 data_blob_clear_free(&password_blob);
189 END_PROFILE(SMBtcon);
190 return ERROR_NT(nt_status);
193 outsize = set_message(outbuf,2,0,True);
194 SSVAL(outbuf,smb_vwv0,max_recv);
195 SSVAL(outbuf,smb_vwv1,conn->cnum);
196 SSVAL(outbuf,smb_tid,conn->cnum);
198 DEBUG(3,("tcon service=%s cnum=%d\n",
199 service, conn->cnum));
201 END_PROFILE(SMBtcon);
205 /****************************************************************************
206 Reply to a tcon and X.
207 ****************************************************************************/
209 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
214 /* what the cleint thinks the device is */
215 fstring client_devicetype;
216 /* what the server tells the client the share represents */
217 const char *server_devicetype;
219 uint16 vuid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
223 extern BOOL global_encrypted_passwords_negotiated;
225 START_PROFILE(SMBtconX);
227 *service = *client_devicetype = 0;
229 /* we might have to close an old one */
230 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
231 close_cnum(conn,vuid);
234 if (passlen > MAX_PASS_LEN) {
235 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
238 if (global_encrypted_passwords_negotiated) {
239 password = data_blob(smb_buf(inbuf),passlen);
241 password = data_blob(smb_buf(inbuf),passlen+1);
242 /* Ensure correct termination */
243 password.data[passlen]=0;
246 p = smb_buf(inbuf) + passlen;
247 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
250 * the service name can be either: \\server\share
251 * or share directly like on the DELL PowerVault 705
254 q = strchr_m(path+2,'\\');
256 END_PROFILE(SMBtconX);
257 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
259 fstrcpy(service,q+1);
262 fstrcpy(service,path);
264 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
266 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
268 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
270 data_blob_clear_free(&password);
273 END_PROFILE(SMBtconX);
274 return ERROR_NT(nt_status);
278 server_devicetype = "IPC";
279 else if ( IS_PRINT(conn) )
280 server_devicetype = "LPT1:";
282 server_devicetype = "A:";
284 if (Protocol < PROTOCOL_NT1) {
285 set_message(outbuf,2,0,True);
287 p += srvstr_push(outbuf, p, server_devicetype, -1,
288 STR_TERMINATE|STR_ASCII);
289 set_message_end(outbuf,p);
291 /* NT sets the fstype of IPC$ to the null string */
292 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
294 set_message(outbuf,3,0,True);
297 p += srvstr_push(outbuf, p, server_devicetype, -1,
298 STR_TERMINATE|STR_ASCII);
299 p += srvstr_push(outbuf, p, fstype, -1,
302 set_message_end(outbuf,p);
304 /* what does setting this bit do? It is set by NT4 and
305 may affect the ability to autorun mounted cdroms */
306 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
307 (lp_csc_policy(SNUM(conn)) << 2));
309 init_dfsroot(conn, inbuf, outbuf);
313 DEBUG(3,("tconX service=%s \n",
316 /* set the incoming and outgoing tid to the just created one */
317 SSVAL(inbuf,smb_tid,conn->cnum);
318 SSVAL(outbuf,smb_tid,conn->cnum);
320 END_PROFILE(SMBtconX);
321 return chain_reply(inbuf,outbuf,length,bufsize);
324 /****************************************************************************
325 Reply to an unknown type.
326 ****************************************************************************/
328 int reply_unknown(char *inbuf,char *outbuf)
331 type = CVAL(inbuf,smb_com);
333 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
334 smb_fn_name(type), type, type));
336 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
339 /****************************************************************************
341 ****************************************************************************/
343 int reply_ioctl(connection_struct *conn,
344 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
346 uint16 device = SVAL(inbuf,smb_vwv1);
347 uint16 function = SVAL(inbuf,smb_vwv2);
348 uint32 ioctl_code = (device << 16) + function;
349 int replysize, outsize;
351 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
352 START_PROFILE(SMBioctl);
354 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
356 switch (ioctl_code) {
357 case IOCTL_QUERY_JOB_INFO:
361 END_PROFILE(SMBioctl);
362 return(ERROR_DOS(ERRSRV,ERRnosupport));
365 outsize = set_message(outbuf,8,replysize+1,True);
366 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
367 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
368 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
369 p = smb_buf(outbuf) + 1; /* Allow for alignment */
371 switch (ioctl_code) {
372 case IOCTL_QUERY_JOB_INFO:
374 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
375 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
376 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
381 END_PROFILE(SMBioctl);
385 /****************************************************************************
387 ****************************************************************************/
389 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
395 BOOL bad_path = False;
396 SMB_STRUCT_STAT sbuf;
399 START_PROFILE(SMBchkpth);
401 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
403 status = check_path_syntax(name);
404 if (!NT_STATUS_IS_OK(status))
405 return ERROR_NT(status);
407 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
409 unix_convert(name,conn,0,&bad_path,&sbuf);
411 mode = SVAL(inbuf,smb_vwv0);
413 if (check_name(name,conn)) {
414 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
415 if (!(ok = S_ISDIR(sbuf.st_mode)))
420 /* We special case this - as when a Windows machine
421 is parsing a path is steps through the components
422 one at a time - if a component fails it expects
423 ERRbadpath, not ERRbadfile.
425 if(errno == ENOENT) {
427 * Windows returns different error codes if
428 * the parent directory is valid but not the
429 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
430 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
431 * if the path is invalid.
434 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
436 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
438 } else if (errno == ENOTDIR)
439 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
441 return(UNIXERROR(ERRDOS,ERRbadpath));
444 outsize = set_message(outbuf,0,0,True);
446 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
448 END_PROFILE(SMBchkpth);
452 /****************************************************************************
454 ****************************************************************************/
456 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
460 SMB_STRUCT_STAT sbuf;
465 BOOL bad_path = False;
467 START_PROFILE(SMBgetatr);
469 p = smb_buf(inbuf) + 1;
470 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
472 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
474 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
475 under WfWg - weird! */
477 mode = aHIDDEN | aDIR;
478 if (!CAN_WRITE(conn))
484 unix_convert(fname,conn,0,&bad_path,&sbuf);
485 if (check_name(fname,conn)) {
486 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
487 mode = dos_mode(conn,fname,&sbuf);
489 mtime = sbuf.st_mtime;
494 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
500 END_PROFILE(SMBgetatr);
501 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
504 outsize = set_message(outbuf,10,0,True);
506 SSVAL(outbuf,smb_vwv0,mode);
507 if(lp_dos_filetime_resolution(SNUM(conn)) )
508 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
510 put_dos_date3(outbuf,smb_vwv1,mtime);
511 SIVAL(outbuf,smb_vwv3,(uint32)size);
513 if (Protocol >= PROTOCOL_NT1)
514 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
516 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
518 END_PROFILE(SMBgetatr);
522 /****************************************************************************
524 ****************************************************************************/
526 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
533 SMB_STRUCT_STAT sbuf;
534 BOOL bad_path = False;
537 START_PROFILE(SMBsetatr);
539 p = smb_buf(inbuf) + 1;
540 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
541 unix_convert(fname,conn,0,&bad_path,&sbuf);
543 mode = SVAL(inbuf,smb_vwv0);
544 mtime = make_unix_date3(inbuf+smb_vwv1);
546 if (mode != FILE_ATTRIBUTE_NORMAL) {
547 if (VALID_STAT_OF_DIR(sbuf))
552 if (check_name(fname,conn))
553 ok = (file_chmod(conn,fname,mode,NULL) == 0);
559 ok = set_filetime(conn,fname,mtime);
562 END_PROFILE(SMBsetatr);
563 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
566 outsize = set_message(outbuf,0,0,True);
568 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
570 END_PROFILE(SMBsetatr);
574 /****************************************************************************
576 ****************************************************************************/
578 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
581 SMB_BIG_UINT dfree,dsize,bsize;
582 START_PROFILE(SMBdskattr);
584 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
586 outsize = set_message(outbuf,5,0,True);
588 if (Protocol <= PROTOCOL_LANMAN2) {
589 double total_space, free_space;
590 /* we need to scale this to a number that DOS6 can handle. We
591 use floating point so we can handle large drives on systems
592 that don't have 64 bit integers
594 we end up displaying a maximum of 2G to DOS systems
596 total_space = dsize * (double)bsize;
597 free_space = dfree * (double)bsize;
599 dsize = (total_space+63*512) / (64*512);
600 dfree = (free_space+63*512) / (64*512);
602 if (dsize > 0xFFFF) dsize = 0xFFFF;
603 if (dfree > 0xFFFF) dfree = 0xFFFF;
605 SSVAL(outbuf,smb_vwv0,dsize);
606 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
607 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
608 SSVAL(outbuf,smb_vwv3,dfree);
610 SSVAL(outbuf,smb_vwv0,dsize);
611 SSVAL(outbuf,smb_vwv1,bsize/512);
612 SSVAL(outbuf,smb_vwv2,512);
613 SSVAL(outbuf,smb_vwv3,dfree);
616 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
618 END_PROFILE(SMBdskattr);
622 /****************************************************************************
624 Can be called from SMBsearch, SMBffirst or SMBfunique.
625 ****************************************************************************/
627 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
638 BOOL finished = False;
647 BOOL check_descend = False;
648 BOOL expect_close = False;
649 BOOL can_open = True;
650 BOOL bad_path = False;
651 START_PROFILE(SMBsearch);
653 *mask = *directory = *fname = 0;
655 /* If we were called as SMBffirst then we must expect close. */
656 if(CVAL(inbuf,smb_com) == SMBffirst)
659 outsize = set_message(outbuf,1,3,True);
660 maxentries = SVAL(inbuf,smb_vwv0);
661 dirtype = SVAL(inbuf,smb_vwv1);
662 p = smb_buf(inbuf) + 1;
663 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
665 status_len = SVAL(p, 0);
668 /* dirtype &= ~aDIR; */
670 if (status_len == 0) {
671 SMB_STRUCT_STAT sbuf;
674 pstrcpy(directory,path);
676 unix_convert(directory,conn,0,&bad_path,&sbuf);
679 if (!check_name(directory,conn))
682 p = strrchr_m(dir2,'/');
691 p = strrchr_m(directory,'/');
697 if (strlen(directory) == 0)
698 pstrcpy(directory,".");
699 memset((char *)status,'\0',21);
700 SCVAL(status,0,(dirtype & 0x1F));
705 status_dirtype = CVAL(status,0) & 0x1F;
706 if (status_dirtype != (dirtype & 0x1F))
707 dirtype = status_dirtype;
709 conn->dirptr = dptr_fetch(status+12,&dptr_num);
712 string_set(&conn->dirpath,dptr_path(dptr_num));
713 pstrcpy(mask, dptr_wcard(dptr_num));
717 p = smb_buf(outbuf) + 3;
720 if (status_len == 0) {
721 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
724 END_PROFILE(SMBsearch);
725 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
727 END_PROFILE(SMBsearch);
728 return ERROR_DOS(ERRDOS,ERRnofids);
730 dptr_set_wcard(dptr_num, strdup(mask));
731 dptr_set_attr(dptr_num, dirtype);
733 dirtype = dptr_attr(dptr_num);
736 DEBUG(4,("dptr_num is %d\n",dptr_num));
739 if ((dirtype&0x1F) == aVOLID) {
741 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
742 dptr_fill(p+12,dptr_num);
743 if (dptr_zero(p+12) && (status_len==0))
747 p += DIR_STRUCT_SIZE;
749 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
750 conn->dirpath,lp_dontdescend(SNUM(conn))));
751 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
752 check_descend = True;
754 for (i=numentries;(i<maxentries) && !finished;i++) {
755 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
758 make_dir_struct(p,mask,fname,size,mode,date);
759 dptr_fill(p+12,dptr_num);
762 p += DIR_STRUCT_SIZE;
771 if (numentries == 0 || !ok) {
772 SCVAL(outbuf,smb_rcls,ERRDOS);
773 SSVAL(outbuf,smb_err,ERRnofiles);
774 dptr_close(&dptr_num);
777 /* If we were called as SMBffirst with smb_search_id == NULL
778 and no entries were found then return error and close dirptr
781 if(ok && expect_close && numentries == 0 && status_len == 0) {
782 SCVAL(outbuf,smb_rcls,ERRDOS);
783 SSVAL(outbuf,smb_err,ERRnofiles);
784 /* Also close the dptr - we know it's gone */
785 dptr_close(&dptr_num);
788 /* If we were called as SMBfunique, then we can close the dirptr now ! */
789 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
790 dptr_close(&dptr_num);
792 SSVAL(outbuf,smb_vwv0,numentries);
793 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
794 SCVAL(smb_buf(outbuf),0,5);
795 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
797 if (Protocol >= PROTOCOL_NT1)
798 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
800 outsize += DIR_STRUCT_SIZE*numentries;
801 smb_setlen(outbuf,outsize - 4);
803 if ((! *directory) && dptr_path(dptr_num))
804 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
806 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
807 smb_fn_name(CVAL(inbuf,smb_com)),
808 mask, directory, dirtype, numentries, maxentries ) );
810 END_PROFILE(SMBsearch);
814 /****************************************************************************
815 Reply to a fclose (stop directory search).
816 ****************************************************************************/
818 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
827 START_PROFILE(SMBfclose);
829 outsize = set_message(outbuf,1,0,True);
830 p = smb_buf(inbuf) + 1;
831 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
833 status_len = SVAL(p,0);
836 if (status_len == 0) {
837 END_PROFILE(SMBfclose);
838 return ERROR_DOS(ERRSRV,ERRsrverror);
843 if(dptr_fetch(status+12,&dptr_num)) {
844 /* Close the dptr - we know it's gone */
845 dptr_close(&dptr_num);
848 SSVAL(outbuf,smb_vwv0,0);
850 DEBUG(3,("search close\n"));
852 END_PROFILE(SMBfclose);
856 /****************************************************************************
858 ****************************************************************************/
860 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
870 SMB_STRUCT_STAT sbuf;
871 BOOL bad_path = False;
873 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
874 START_PROFILE(SMBopen);
876 share_mode = SVAL(inbuf,smb_vwv0);
878 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
880 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
882 unix_convert(fname,conn,0,&bad_path,&sbuf);
884 unixmode = unix_mode(conn,aARCH,fname);
886 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
887 unixmode, oplock_request,&rmode,NULL);
890 END_PROFILE(SMBopen);
891 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
895 fmode = dos_mode(conn,fname,&sbuf);
896 mtime = sbuf.st_mtime;
899 DEBUG(3,("attempt to open a directory %s\n",fname));
900 close_file(fsp,False);
901 END_PROFILE(SMBopen);
902 return ERROR_DOS(ERRDOS,ERRnoaccess);
905 outsize = set_message(outbuf,7,0,True);
906 SSVAL(outbuf,smb_vwv0,fsp->fnum);
907 SSVAL(outbuf,smb_vwv1,fmode);
908 if(lp_dos_filetime_resolution(SNUM(conn)) )
909 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
911 put_dos_date3(outbuf,smb_vwv2,mtime);
912 SIVAL(outbuf,smb_vwv4,(uint32)size);
913 SSVAL(outbuf,smb_vwv6,rmode);
915 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
916 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
918 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
919 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
920 END_PROFILE(SMBopen);
924 /****************************************************************************
925 Reply to an open and X.
926 ****************************************************************************/
928 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
931 int smb_mode = SVAL(inbuf,smb_vwv3);
932 int smb_attr = SVAL(inbuf,smb_vwv5);
933 /* Breakout the oplock request bits so we can set the
934 reply bits separately. */
935 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
936 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
937 BOOL oplock_request = ex_oplock_request | core_oplock_request;
939 int open_flags = SVAL(inbuf,smb_vwv2);
940 int smb_sattr = SVAL(inbuf,smb_vwv4);
941 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
943 int smb_ofun = SVAL(inbuf,smb_vwv8);
946 int fmode=0,mtime=0,rmode=0;
947 SMB_STRUCT_STAT sbuf;
949 BOOL bad_path = False;
951 START_PROFILE(SMBopenX);
953 /* If it's an IPC, pass off the pipe handler. */
955 if (lp_nt_pipe_support()) {
956 END_PROFILE(SMBopenX);
957 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
959 END_PROFILE(SMBopenX);
960 return ERROR_DOS(ERRSRV,ERRaccess);
964 /* XXXX we need to handle passed times, sattr and flags */
965 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
967 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
969 unix_convert(fname,conn,0,&bad_path,&sbuf);
971 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
973 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
974 oplock_request, &rmode,&smb_action);
977 END_PROFILE(SMBopenX);
978 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
982 fmode = dos_mode(conn,fname,&sbuf);
983 mtime = sbuf.st_mtime;
985 close_file(fsp,False);
986 END_PROFILE(SMBopenX);
987 return ERROR_DOS(ERRDOS,ERRnoaccess);
990 /* If the caller set the extended oplock request bit
991 and we granted one (by whatever means) - set the
992 correct bit for extended oplock reply.
995 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
996 smb_action |= EXTENDED_OPLOCK_GRANTED;
998 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
999 smb_action |= EXTENDED_OPLOCK_GRANTED;
1001 /* If the caller set the core oplock request bit
1002 and we granted one (by whatever means) - set the
1003 correct bit for core oplock reply.
1006 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1007 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1009 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1010 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1012 set_message(outbuf,15,0,True);
1013 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1014 SSVAL(outbuf,smb_vwv3,fmode);
1015 if(lp_dos_filetime_resolution(SNUM(conn)) )
1016 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1018 put_dos_date3(outbuf,smb_vwv4,mtime);
1019 SIVAL(outbuf,smb_vwv6,(uint32)size);
1020 SSVAL(outbuf,smb_vwv8,rmode);
1021 SSVAL(outbuf,smb_vwv11,smb_action);
1023 END_PROFILE(SMBopenX);
1024 return chain_reply(inbuf,outbuf,length,bufsize);
1027 /****************************************************************************
1028 Reply to a SMBulogoffX.
1029 ****************************************************************************/
1031 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1033 uint16 vuid = SVAL(inbuf,smb_uid);
1034 user_struct *vuser = get_valid_user_struct(vuid);
1035 START_PROFILE(SMBulogoffX);
1038 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1040 /* in user level security we are supposed to close any files
1041 open by this user */
1042 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1043 file_close_user(vuid);
1045 invalidate_vuid(vuid);
1047 set_message(outbuf,2,0,True);
1049 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1051 END_PROFILE(SMBulogoffX);
1052 return chain_reply(inbuf,outbuf,length,bufsize);
1055 /****************************************************************************
1056 Reply to a mknew or a create.
1057 ****************************************************************************/
1059 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1067 BOOL bad_path = False;
1069 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1070 SMB_STRUCT_STAT sbuf;
1071 START_PROFILE(SMBcreate);
1073 com = SVAL(inbuf,smb_com);
1075 createmode = SVAL(inbuf,smb_vwv0);
1076 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1078 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1080 unix_convert(fname,conn,0,&bad_path,&sbuf);
1082 if (createmode & aVOLID)
1083 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1085 unixmode = unix_mode(conn,createmode,fname);
1087 if(com == SMBmknew) {
1088 /* We should fail if file exists. */
1089 ofun = FILE_CREATE_IF_NOT_EXIST;
1091 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1092 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1095 /* Open file in dos compatibility share mode. */
1096 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1097 ofun, unixmode, oplock_request, NULL, NULL);
1100 END_PROFILE(SMBcreate);
1101 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1104 outsize = set_message(outbuf,1,0,True);
1105 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1107 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1108 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1110 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1111 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1113 DEBUG( 2, ( "new file %s\n", fname ) );
1114 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1116 END_PROFILE(SMBcreate);
1120 /****************************************************************************
1121 Reply to a create temporary file.
1122 ****************************************************************************/
1124 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1130 BOOL bad_path = False;
1132 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1134 SMB_STRUCT_STAT sbuf;
1137 START_PROFILE(SMBctemp);
1139 createmode = SVAL(inbuf,smb_vwv0);
1140 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1141 pstrcat(fname,"\\TMXXXXXX");
1143 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1145 unix_convert(fname,conn,0,&bad_path,&sbuf);
1147 unixmode = unix_mode(conn,createmode,fname);
1149 tmpfd = smb_mkstemp(fname);
1151 END_PROFILE(SMBctemp);
1152 return(UNIXERROR(ERRDOS,ERRnoaccess));
1155 SMB_VFS_STAT(conn,fname,&sbuf);
1157 /* Open file in dos compatibility share mode. */
1158 /* We should fail if file does not exist. */
1159 fsp = open_file_shared(conn,fname,&sbuf,
1160 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1161 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1162 unixmode, oplock_request, NULL, NULL);
1164 /* close fd from smb_mkstemp() */
1168 END_PROFILE(SMBctemp);
1169 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1172 outsize = set_message(outbuf,1,0,True);
1173 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1175 /* the returned filename is relative to the directory */
1176 s = strrchr_m(fname, '/');
1182 p = smb_buf(outbuf);
1183 SSVALS(p, 0, -1); /* what is this? not in spec */
1184 SSVAL(p, 2, strlen(s));
1186 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1187 outsize = set_message_end(outbuf, p);
1189 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1190 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1192 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1193 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1195 DEBUG( 2, ( "created temp file %s\n", fname ) );
1196 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1197 fname, fsp->fd, createmode, (int)unixmode ) );
1199 END_PROFILE(SMBctemp);
1203 /*******************************************************************
1204 Check if a user is allowed to rename a file.
1205 ********************************************************************/
1207 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1213 if (!CAN_WRITE(conn))
1214 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1216 if (S_ISDIR(pst->st_mode))
1217 return NT_STATUS_OK;
1219 /* We need a better way to return NT status codes from open... */
1223 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1224 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1227 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1228 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1229 ret = NT_STATUS_SHARING_VIOLATION;
1234 close_file(fsp,False);
1235 return NT_STATUS_OK;
1238 /*******************************************************************
1239 Check if a user is allowed to delete a file.
1240 ********************************************************************/
1242 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1244 SMB_STRUCT_STAT sbuf;
1250 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1253 if (!CAN_WRITE(conn))
1254 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1256 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1257 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1259 fmode = dos_mode(conn,fname,&sbuf);
1261 /* Can't delete a directory. */
1263 return NT_STATUS_FILE_IS_A_DIRECTORY;
1265 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1266 return NT_STATUS_OBJECT_NAME_INVALID;
1267 #endif /* JRATEST */
1269 if (!lp_delete_readonly(SNUM(conn))) {
1271 return NT_STATUS_CANNOT_DELETE;
1273 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1274 return NT_STATUS_NO_SUCH_FILE;
1276 /* We need a better way to return NT status codes from open... */
1280 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1281 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1284 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1285 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1286 ret = unix_ERR_ntstatus;
1287 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1288 ret = NT_STATUS_SHARING_VIOLATION;
1291 unix_ERR_ntstatus = NT_STATUS_OK;
1294 close_file(fsp,False);
1295 return NT_STATUS_OK;
1298 /****************************************************************************
1299 The guts of the unlink command, split out so it may be called by the NT SMB
1301 ****************************************************************************/
1303 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1309 NTSTATUS error = NT_STATUS_OK;
1311 BOOL bad_path = False;
1313 SMB_STRUCT_STAT sbuf;
1315 *directory = *mask = 0;
1317 /* We must check for wildcards in the name given
1318 * directly by the client - before any unmangling.
1319 * This prevents an unmangling of a UNIX name containing
1320 * a DOS wildcard like '*' or '?' from unmangling into
1321 * a wildcard delete which was not intended.
1322 * FIX for #226. JRA.
1325 has_wild = ms_has_wild(name);
1327 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1329 p = strrchr_m(name,'/');
1331 pstrcpy(directory,".");
1335 pstrcpy(directory,name);
1340 * We should only check the mangled cache
1341 * here if unix_convert failed. This means
1342 * that the path in 'mask' doesn't exist
1343 * on the file system and so we need to look
1344 * for a possible mangle. This patch from
1345 * Tine Smukavec <valentin.smukavec@hermes.si>.
1348 if (!rc && mangle_is_mangled(mask))
1349 mangle_check_cache( mask );
1352 pstrcat(directory,"/");
1353 pstrcat(directory,mask);
1354 error = can_delete(directory,conn,dirtype);
1355 if (!NT_STATUS_IS_OK(error))
1358 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1362 void *dirptr = NULL;
1365 if (check_name(directory,conn))
1366 dirptr = OpenDir(conn, directory, True);
1368 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1369 the pattern matches against the long name, otherwise the short name
1370 We don't implement this yet XXXX
1374 error = NT_STATUS_NO_SUCH_FILE;
1376 if (strequal(mask,"????????.???"))
1379 while ((dname = ReadDirName(dirptr))) {
1381 pstrcpy(fname,dname);
1383 if(!mask_match(fname, mask, case_sensitive))
1386 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1387 error = can_delete(fname,conn,dirtype);
1388 if (!NT_STATUS_IS_OK(error))
1390 if (SMB_VFS_UNLINK(conn,fname) == 0)
1392 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1398 if (count == 0 && NT_STATUS_IS_OK(error)) {
1399 error = map_nt_error_from_unix(errno);
1405 /****************************************************************************
1407 ****************************************************************************/
1409 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1416 START_PROFILE(SMBunlink);
1418 dirtype = SVAL(inbuf,smb_vwv0);
1420 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1422 status = check_path_syntax(name);
1423 if (!NT_STATUS_IS_OK(status))
1424 return ERROR_NT(status);
1426 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1428 DEBUG(3,("reply_unlink : %s\n",name));
1430 status = unlink_internals(conn, dirtype, name);
1431 if (!NT_STATUS_IS_OK(status))
1432 return ERROR_NT(status);
1435 * Win2k needs a changenotify request response before it will
1436 * update after a rename..
1438 process_pending_change_notify_queue((time_t)0);
1440 outsize = set_message(outbuf,0,0,True);
1442 END_PROFILE(SMBunlink);
1446 /****************************************************************************
1448 ****************************************************************************/
1450 void fail_readraw(void)
1453 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1455 exit_server(errstr);
1458 /****************************************************************************
1459 Use sendfile in readbraw.
1460 ****************************************************************************/
1462 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1463 ssize_t mincount, char *outbuf)
1467 #if defined(WITH_SENDFILE)
1469 * We can only use sendfile on a non-chained packet and on a file
1470 * that is exclusively oplocked. reply_readbraw has already checked the length.
1473 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1474 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1477 _smb_setlen(outbuf,nread);
1478 header.data = outbuf;
1482 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1484 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1485 * return ENOSYS then pretend we just got a normal read.
1487 if (errno == ENOSYS)
1490 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1491 fsp->fsp_name, strerror(errno) ));
1492 exit_server("send_file_readbraw sendfile failed");
1501 ret = read_file(fsp,outbuf+4,startpos,nread);
1506 _smb_setlen(outbuf,ret);
1507 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1511 /****************************************************************************
1512 Reply to a readbraw (core+ protocol).
1513 ****************************************************************************/
1515 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1517 extern struct current_user current_user;
1518 ssize_t maxcount,mincount;
1521 char *header = outbuf;
1523 START_PROFILE(SMBreadbraw);
1525 if (srv_is_signing_active()) {
1526 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1530 * Special check if an oplock break has been issued
1531 * and the readraw request croses on the wire, we must
1532 * return a zero length response here.
1535 if(global_oplock_break) {
1536 _smb_setlen(header,0);
1537 if (write_data(smbd_server_fd(),header,4) != 4)
1539 DEBUG(5,("readbraw - oplock break finished\n"));
1540 END_PROFILE(SMBreadbraw);
1544 fsp = file_fsp(inbuf,smb_vwv0);
1546 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1548 * fsp could be NULL here so use the value from the packet. JRA.
1550 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1551 _smb_setlen(header,0);
1552 if (write_data(smbd_server_fd(),header,4) != 4)
1554 END_PROFILE(SMBreadbraw);
1558 CHECK_FSP(fsp,conn);
1560 flush_write_cache(fsp, READRAW_FLUSH);
1562 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1563 if(CVAL(inbuf,smb_wct) == 10) {
1565 * This is a large offset (64 bit) read.
1567 #ifdef LARGE_SMB_OFF_T
1569 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1571 #else /* !LARGE_SMB_OFF_T */
1574 * Ensure we haven't been sent a >32 bit offset.
1577 if(IVAL(inbuf,smb_vwv8) != 0) {
1578 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1579 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1580 _smb_setlen(header,0);
1581 if (write_data(smbd_server_fd(),header,4) != 4)
1583 END_PROFILE(SMBreadbraw);
1587 #endif /* LARGE_SMB_OFF_T */
1590 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1591 _smb_setlen(header,0);
1592 if (write_data(smbd_server_fd(),header,4) != 4)
1594 END_PROFILE(SMBreadbraw);
1598 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1599 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1601 /* ensure we don't overrun the packet size */
1602 maxcount = MIN(65535,maxcount);
1603 maxcount = MAX(mincount,maxcount);
1605 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1606 SMB_OFF_T size = fsp->size;
1607 SMB_OFF_T sizeneeded = startpos + maxcount;
1609 if (size < sizeneeded) {
1611 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1613 if (!fsp->can_write)
1617 if (startpos >= size)
1620 nread = MIN(maxcount,(size - startpos));
1623 if (nread < mincount)
1626 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1627 (int)maxcount, (int)mincount, (int)nread ) );
1629 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1631 DEBUG(5,("readbraw finished\n"));
1632 END_PROFILE(SMBreadbraw);
1636 /****************************************************************************
1637 Reply to a lockread (core+ protocol).
1638 ****************************************************************************/
1640 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1648 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1649 START_PROFILE(SMBlockread);
1651 CHECK_FSP(fsp,conn);
1654 release_level_2_oplocks_on_change(fsp);
1656 numtoread = SVAL(inbuf,smb_vwv1);
1657 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1659 outsize = set_message(outbuf,5,3,True);
1660 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1661 data = smb_buf(outbuf) + 3;
1664 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1665 * protocol request that predates the read/write lock concept.
1666 * Thus instead of asking for a read lock here we need to ask
1667 * for a write lock. JRA.
1670 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1671 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1673 if (NT_STATUS_V(status)) {
1674 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1676 * A blocking lock was requested. Package up
1677 * this smb into a queued request and push it
1678 * onto the blocking lock queue.
1680 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1681 (SMB_BIG_UINT)numtoread)) {
1682 END_PROFILE(SMBlockread);
1686 END_PROFILE(SMBlockread);
1687 return ERROR_NT(status);
1690 nread = read_file(fsp,data,startpos,numtoread);
1693 END_PROFILE(SMBlockread);
1694 return(UNIXERROR(ERRDOS,ERRnoaccess));
1698 SSVAL(outbuf,smb_vwv0,nread);
1699 SSVAL(outbuf,smb_vwv5,nread+3);
1700 SSVAL(smb_buf(outbuf),1,nread);
1702 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1703 fsp->fnum, (int)numtoread, (int)nread));
1705 END_PROFILE(SMBlockread);
1709 /****************************************************************************
1711 ****************************************************************************/
1713 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1720 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1721 START_PROFILE(SMBread);
1723 CHECK_FSP(fsp,conn);
1726 numtoread = SVAL(inbuf,smb_vwv1);
1727 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1729 outsize = set_message(outbuf,5,3,True);
1730 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1731 data = smb_buf(outbuf) + 3;
1733 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1734 END_PROFILE(SMBread);
1735 return ERROR_DOS(ERRDOS,ERRlock);
1739 nread = read_file(fsp,data,startpos,numtoread);
1742 END_PROFILE(SMBread);
1743 return(UNIXERROR(ERRDOS,ERRnoaccess));
1747 SSVAL(outbuf,smb_vwv0,nread);
1748 SSVAL(outbuf,smb_vwv5,nread+3);
1749 SCVAL(smb_buf(outbuf),0,1);
1750 SSVAL(smb_buf(outbuf),1,nread);
1752 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1753 fsp->fnum, (int)numtoread, (int)nread ) );
1755 END_PROFILE(SMBread);
1759 /****************************************************************************
1760 Reply to a read and X - possibly using sendfile.
1761 ****************************************************************************/
1763 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1764 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1767 char *data = smb_buf(outbuf);
1769 #if defined(WITH_SENDFILE)
1771 * We can only use sendfile on a non-chained packet and on a file
1772 * that is exclusively oplocked.
1775 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1776 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1777 SMB_STRUCT_STAT sbuf;
1780 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1781 return(UNIXERROR(ERRDOS,ERRnoaccess));
1783 if (startpos > sbuf.st_size)
1786 if (smb_maxcnt > (sbuf.st_size - startpos))
1787 smb_maxcnt = (sbuf.st_size - startpos);
1789 if (smb_maxcnt == 0)
1793 * Set up the packet header before send. We
1794 * assume here the sendfile will work (get the
1795 * correct amount of data).
1798 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1799 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1800 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1801 SCVAL(outbuf,smb_vwv0,0xFF);
1802 set_message(outbuf,12,smb_maxcnt,False);
1803 header.data = outbuf;
1804 header.length = data - outbuf;
1807 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1809 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1810 * return ENOSYS then pretend we just got a normal read.
1812 if (errno == ENOSYS)
1815 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1816 fsp->fsp_name, strerror(errno) ));
1817 exit_server("send_file_readX sendfile failed");
1820 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1821 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1829 nread = read_file(fsp,data,startpos,smb_maxcnt);
1832 END_PROFILE(SMBreadX);
1833 return(UNIXERROR(ERRDOS,ERRnoaccess));
1836 SSVAL(outbuf,smb_vwv5,nread);
1837 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1838 SSVAL(smb_buf(outbuf),-2,nread);
1840 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1841 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1846 /****************************************************************************
1847 Reply to a read and X.
1848 ****************************************************************************/
1850 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1852 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1853 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1855 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1857 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1860 START_PROFILE(SMBreadX);
1862 /* If it's an IPC, pass off the pipe handler. */
1864 END_PROFILE(SMBreadX);
1865 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1868 CHECK_FSP(fsp,conn);
1871 set_message(outbuf,12,0,True);
1873 if(CVAL(inbuf,smb_wct) == 12) {
1874 #ifdef LARGE_SMB_OFF_T
1876 * This is a large offset (64 bit) read.
1878 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1880 #else /* !LARGE_SMB_OFF_T */
1883 * Ensure we haven't been sent a >32 bit offset.
1886 if(IVAL(inbuf,smb_vwv10) != 0) {
1887 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1888 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1889 END_PROFILE(SMBreadX);
1890 return ERROR_DOS(ERRDOS,ERRbadaccess);
1893 #endif /* LARGE_SMB_OFF_T */
1897 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1898 END_PROFILE(SMBreadX);
1899 return ERROR_DOS(ERRDOS,ERRlock);
1902 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1904 nread = chain_reply(inbuf,outbuf,length,bufsize);
1906 END_PROFILE(SMBreadX);
1910 /****************************************************************************
1911 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1912 ****************************************************************************/
1914 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1917 ssize_t total_written=0;
1918 size_t numtowrite=0;
1923 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1925 START_PROFILE(SMBwritebraw);
1927 if (srv_is_signing_active()) {
1928 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1931 CHECK_FSP(fsp,conn);
1934 tcount = IVAL(inbuf,smb_vwv1);
1935 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1936 write_through = BITSETW(inbuf+smb_vwv7,0);
1938 /* We have to deal with slightly different formats depending
1939 on whether we are using the core+ or lanman1.0 protocol */
1941 if(Protocol <= PROTOCOL_COREPLUS) {
1942 numtowrite = SVAL(smb_buf(inbuf),-2);
1943 data = smb_buf(inbuf);
1945 numtowrite = SVAL(inbuf,smb_vwv10);
1946 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1949 /* force the error type */
1950 SCVAL(inbuf,smb_com,SMBwritec);
1951 SCVAL(outbuf,smb_com,SMBwritec);
1953 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1954 END_PROFILE(SMBwritebraw);
1955 return(ERROR_DOS(ERRDOS,ERRlock));
1959 nwritten = write_file(fsp,data,startpos,numtowrite);
1961 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1962 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1964 if (nwritten < (ssize_t)numtowrite) {
1965 END_PROFILE(SMBwritebraw);
1966 return(UNIXERROR(ERRHRD,ERRdiskfull));
1969 total_written = nwritten;
1971 /* Return a message to the redirector to tell it to send more bytes */
1972 SCVAL(outbuf,smb_com,SMBwritebraw);
1973 SSVALS(outbuf,smb_vwv0,-1);
1974 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1975 if (!send_smb(smbd_server_fd(),outbuf))
1976 exit_server("reply_writebraw: send_smb failed.");
1978 /* Now read the raw data into the buffer and write it */
1979 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1980 exit_server("secondary writebraw failed");
1983 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1984 numtowrite = smb_len(inbuf);
1986 /* Set up outbuf to return the correct return */
1987 outsize = set_message(outbuf,1,0,True);
1988 SCVAL(outbuf,smb_com,SMBwritec);
1989 SSVAL(outbuf,smb_vwv0,total_written);
1991 if (numtowrite != 0) {
1993 if (numtowrite > BUFFER_SIZE) {
1994 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1995 (unsigned int)numtowrite ));
1996 exit_server("secondary writebraw failed");
1999 if (tcount > nwritten+numtowrite) {
2000 DEBUG(3,("Client overestimated the write %d %d %d\n",
2001 (int)tcount,(int)nwritten,(int)numtowrite));
2004 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2005 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2007 exit_server("secondary writebraw failed");
2010 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2012 if (nwritten < (ssize_t)numtowrite) {
2013 SCVAL(outbuf,smb_rcls,ERRHRD);
2014 SSVAL(outbuf,smb_err,ERRdiskfull);
2018 total_written += nwritten;
2021 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2022 sync_file(conn,fsp);
2024 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2025 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2027 /* we won't return a status if write through is not selected - this follows what WfWg does */
2028 END_PROFILE(SMBwritebraw);
2029 if (!write_through && total_written==tcount) {
2031 #if RABBIT_PELLET_FIX
2033 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2034 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2036 if (!send_keepalive(smbd_server_fd()))
2037 exit_server("reply_writebraw: send of keepalive failed");
2045 /****************************************************************************
2046 Reply to a writeunlock (core+).
2047 ****************************************************************************/
2049 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2050 int size, int dum_buffsize)
2052 ssize_t nwritten = -1;
2057 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2059 START_PROFILE(SMBwriteunlock);
2061 CHECK_FSP(fsp,conn);
2064 numtowrite = SVAL(inbuf,smb_vwv1);
2065 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2066 data = smb_buf(inbuf) + 3;
2068 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2069 WRITE_LOCK,False)) {
2070 END_PROFILE(SMBwriteunlock);
2071 return ERROR_DOS(ERRDOS,ERRlock);
2074 /* The special X/Open SMB protocol handling of
2075 zero length writes is *NOT* done for
2080 nwritten = write_file(fsp,data,startpos,numtowrite);
2082 if (lp_syncalways(SNUM(conn)))
2083 sync_file(conn,fsp);
2085 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2086 END_PROFILE(SMBwriteunlock);
2087 return(UNIXERROR(ERRHRD,ERRdiskfull));
2090 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2091 (SMB_BIG_UINT)startpos);
2092 if (NT_STATUS_V(status)) {
2093 END_PROFILE(SMBwriteunlock);
2094 return ERROR_NT(status);
2097 outsize = set_message(outbuf,1,0,True);
2099 SSVAL(outbuf,smb_vwv0,nwritten);
2101 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2102 fsp->fnum, (int)numtowrite, (int)nwritten));
2104 END_PROFILE(SMBwriteunlock);
2108 /****************************************************************************
2110 ****************************************************************************/
2112 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2115 ssize_t nwritten = -1;
2118 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2120 START_PROFILE(SMBwrite);
2122 /* If it's an IPC, pass off the pipe handler. */
2124 END_PROFILE(SMBwrite);
2125 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2128 CHECK_FSP(fsp,conn);
2131 numtowrite = SVAL(inbuf,smb_vwv1);
2132 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2133 data = smb_buf(inbuf) + 3;
2135 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2136 END_PROFILE(SMBwrite);
2137 return ERROR_DOS(ERRDOS,ERRlock);
2141 * X/Open SMB protocol says that if smb_vwv1 is
2142 * zero then the file size should be extended or
2143 * truncated to the size given in smb_vwv[2-3].
2146 if(numtowrite == 0) {
2148 * This is actually an allocate call, and set EOF. JRA.
2150 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2152 END_PROFILE(SMBwrite);
2153 return ERROR_NT(NT_STATUS_DISK_FULL);
2155 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2157 END_PROFILE(SMBwrite);
2158 return ERROR_NT(NT_STATUS_DISK_FULL);
2161 nwritten = write_file(fsp,data,startpos,numtowrite);
2163 if (lp_syncalways(SNUM(conn)))
2164 sync_file(conn,fsp);
2166 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2167 END_PROFILE(SMBwrite);
2168 return(UNIXERROR(ERRHRD,ERRdiskfull));
2171 outsize = set_message(outbuf,1,0,True);
2173 SSVAL(outbuf,smb_vwv0,nwritten);
2175 if (nwritten < (ssize_t)numtowrite) {
2176 SCVAL(outbuf,smb_rcls,ERRHRD);
2177 SSVAL(outbuf,smb_err,ERRdiskfull);
2180 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2182 END_PROFILE(SMBwrite);
2186 /****************************************************************************
2187 Reply to a write and X.
2188 ****************************************************************************/
2190 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2192 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2193 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2194 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2195 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2196 ssize_t nwritten = -1;
2197 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2198 unsigned int smblen = smb_len(inbuf);
2200 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2201 START_PROFILE(SMBwriteX);
2203 /* If it's an IPC, pass off the pipe handler. */
2205 END_PROFILE(SMBwriteX);
2206 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2209 CHECK_FSP(fsp,conn);
2212 /* Deal with possible LARGE_WRITEX */
2214 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2216 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2217 END_PROFILE(SMBwriteX);
2218 return ERROR_DOS(ERRDOS,ERRbadmem);
2221 data = smb_base(inbuf) + smb_doff;
2223 if(CVAL(inbuf,smb_wct) == 14) {
2224 #ifdef LARGE_SMB_OFF_T
2226 * This is a large offset (64 bit) write.
2228 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2230 #else /* !LARGE_SMB_OFF_T */
2233 * Ensure we haven't been sent a >32 bit offset.
2236 if(IVAL(inbuf,smb_vwv12) != 0) {
2237 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2238 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2239 END_PROFILE(SMBwriteX);
2240 return ERROR_DOS(ERRDOS,ERRbadaccess);
2243 #endif /* LARGE_SMB_OFF_T */
2246 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2247 END_PROFILE(SMBwriteX);
2248 return ERROR_DOS(ERRDOS,ERRlock);
2251 /* X/Open SMB protocol says that, unlike SMBwrite
2252 if the length is zero then NO truncation is
2253 done, just a write of zero. To truncate a file,
2259 nwritten = write_file(fsp,data,startpos,numtowrite);
2261 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2262 END_PROFILE(SMBwriteX);
2263 return(UNIXERROR(ERRHRD,ERRdiskfull));
2266 set_message(outbuf,6,0,True);
2268 SSVAL(outbuf,smb_vwv2,nwritten);
2270 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2272 if (nwritten < (ssize_t)numtowrite) {
2273 SCVAL(outbuf,smb_rcls,ERRHRD);
2274 SSVAL(outbuf,smb_err,ERRdiskfull);
2277 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2278 fsp->fnum, (int)numtowrite, (int)nwritten));
2280 if (lp_syncalways(SNUM(conn)) || write_through)
2281 sync_file(conn,fsp);
2283 END_PROFILE(SMBwriteX);
2284 return chain_reply(inbuf,outbuf,length,bufsize);
2287 /****************************************************************************
2289 ****************************************************************************/
2291 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2297 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2298 START_PROFILE(SMBlseek);
2300 CHECK_FSP(fsp,conn);
2302 flush_write_cache(fsp, SEEK_FLUSH);
2304 mode = SVAL(inbuf,smb_vwv1) & 3;
2305 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2306 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2315 res = fsp->pos + startpos;
2326 if (umode == SEEK_END) {
2327 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2328 if(errno == EINVAL) {
2329 SMB_OFF_T current_pos = startpos;
2330 SMB_STRUCT_STAT sbuf;
2332 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2333 END_PROFILE(SMBlseek);
2334 return(UNIXERROR(ERRDOS,ERRnoaccess));
2337 current_pos += sbuf.st_size;
2339 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2344 END_PROFILE(SMBlseek);
2345 return(UNIXERROR(ERRDOS,ERRnoaccess));
2351 outsize = set_message(outbuf,2,0,True);
2352 SIVAL(outbuf,smb_vwv0,res);
2354 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2355 fsp->fnum, (double)startpos, (double)res, mode));
2357 END_PROFILE(SMBlseek);
2361 /****************************************************************************
2363 ****************************************************************************/
2365 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2367 int outsize = set_message(outbuf,0,0,True);
2368 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2369 START_PROFILE(SMBflush);
2371 CHECK_FSP(fsp,conn);
2374 file_sync_all(conn);
2376 sync_file(conn,fsp);
2379 DEBUG(3,("flush\n"));
2380 END_PROFILE(SMBflush);
2384 /****************************************************************************
2386 ****************************************************************************/
2388 int reply_exit(connection_struct *conn,
2389 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2392 START_PROFILE(SMBexit);
2393 outsize = set_message(outbuf,0,0,True);
2395 DEBUG(3,("exit\n"));
2397 END_PROFILE(SMBexit);
2401 /****************************************************************************
2402 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2403 ****************************************************************************/
2405 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2408 extern struct current_user current_user;
2411 int32 eclass = 0, err = 0;
2412 files_struct *fsp = NULL;
2413 START_PROFILE(SMBclose);
2415 outsize = set_message(outbuf,0,0,True);
2417 /* If it's an IPC, pass off to the pipe handler. */
2419 END_PROFILE(SMBclose);
2420 return reply_pipe_close(conn, inbuf,outbuf);
2423 fsp = file_fsp(inbuf,smb_vwv0);
2426 * We can only use CHECK_FSP if we know it's not a directory.
2429 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2430 END_PROFILE(SMBclose);
2431 return ERROR_DOS(ERRDOS,ERRbadfid);
2434 if(fsp->is_directory) {
2436 * Special case - close NT SMB directory handle.
2438 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2439 close_file(fsp,True);
2442 * Close ordinary file.
2447 /* Save the name for time set in close. */
2448 pstrcpy( file_name, fsp->fsp_name);
2450 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2452 conn->num_files_open));
2455 * close_file() returns the unix errno if an error
2456 * was detected on close - normally this is due to
2457 * a disk full error. If not then it was probably an I/O error.
2460 if((close_err = close_file(fsp,True)) != 0) {
2462 END_PROFILE(SMBclose);
2463 return (UNIXERROR(ERRHRD,ERRgeneral));
2467 * Now take care of any time sent in the close.
2470 mtime = make_unix_date3(inbuf+smb_vwv1);
2472 /* try and set the date */
2473 set_filetime(conn, file_name, mtime);
2477 /* We have a cached error */
2479 END_PROFILE(SMBclose);
2480 return ERROR_DOS(eclass,err);
2483 END_PROFILE(SMBclose);
2487 /****************************************************************************
2488 Reply to a writeclose (Core+ protocol).
2489 ****************************************************************************/
2491 int reply_writeclose(connection_struct *conn,
2492 char *inbuf,char *outbuf, int size, int dum_buffsize)
2495 ssize_t nwritten = -1;
2501 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2502 START_PROFILE(SMBwriteclose);
2504 CHECK_FSP(fsp,conn);
2507 numtowrite = SVAL(inbuf,smb_vwv1);
2508 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2509 mtime = make_unix_date3(inbuf+smb_vwv4);
2510 data = smb_buf(inbuf) + 1;
2512 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2513 END_PROFILE(SMBwriteclose);
2514 return ERROR_DOS(ERRDOS,ERRlock);
2517 nwritten = write_file(fsp,data,startpos,numtowrite);
2519 set_filetime(conn, fsp->fsp_name,mtime);
2521 close_err = close_file(fsp,True);
2523 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2524 fsp->fnum, (int)numtowrite, (int)nwritten,
2525 conn->num_files_open));
2527 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2528 END_PROFILE(SMBwriteclose);
2529 return(UNIXERROR(ERRHRD,ERRdiskfull));
2532 if(close_err != 0) {
2534 END_PROFILE(SMBwriteclose);
2535 return(UNIXERROR(ERRHRD,ERRgeneral));
2538 outsize = set_message(outbuf,1,0,True);
2540 SSVAL(outbuf,smb_vwv0,nwritten);
2541 END_PROFILE(SMBwriteclose);
2545 /****************************************************************************
2547 ****************************************************************************/
2549 int reply_lock(connection_struct *conn,
2550 char *inbuf,char *outbuf, int length, int dum_buffsize)
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(SMBlock);
2558 CHECK_FSP(fsp,conn);
2560 release_level_2_oplocks_on_change(fsp);
2562 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2563 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2565 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2566 fsp->fd, fsp->fnum, (double)offset, (double)count));
2568 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2569 if (NT_STATUS_V(status)) {
2570 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2572 * A blocking lock was requested. Package up
2573 * this smb into a queued request and push it
2574 * onto the blocking lock queue.
2576 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2577 END_PROFILE(SMBlock);
2581 END_PROFILE(SMBlock);
2582 return ERROR_NT(status);
2585 END_PROFILE(SMBlock);
2589 /****************************************************************************
2591 ****************************************************************************/
2593 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2596 int outsize = set_message(outbuf,0,0,True);
2597 SMB_BIG_UINT count,offset;
2599 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2600 START_PROFILE(SMBunlock);
2602 CHECK_FSP(fsp,conn);
2604 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2605 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2607 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2608 if (NT_STATUS_V(status)) {
2609 END_PROFILE(SMBunlock);
2610 return ERROR_NT(status);
2613 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2614 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2616 END_PROFILE(SMBunlock);
2620 /****************************************************************************
2622 ****************************************************************************/
2624 int reply_tdis(connection_struct *conn,
2625 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2627 int outsize = set_message(outbuf,0,0,True);
2629 START_PROFILE(SMBtdis);
2631 vuid = SVAL(inbuf,smb_uid);
2634 DEBUG(4,("Invalid connection in tdis\n"));
2635 END_PROFILE(SMBtdis);
2636 return ERROR_DOS(ERRSRV,ERRinvnid);
2641 close_cnum(conn,vuid);
2643 END_PROFILE(SMBtdis);
2647 /****************************************************************************
2649 ****************************************************************************/
2651 int reply_echo(connection_struct *conn,
2652 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2654 int smb_reverb = SVAL(inbuf,smb_vwv0);
2656 unsigned int data_len = smb_buflen(inbuf);
2657 int outsize = set_message(outbuf,1,data_len,True);
2658 START_PROFILE(SMBecho);
2660 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2662 /* copy any incoming data back out */
2664 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2666 if (smb_reverb > 100) {
2667 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2671 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2672 SSVAL(outbuf,smb_vwv0,seq_num);
2674 smb_setlen(outbuf,outsize - 4);
2676 if (!send_smb(smbd_server_fd(),outbuf))
2677 exit_server("reply_echo: send_smb failed.");
2680 DEBUG(3,("echo %d times\n", smb_reverb));
2684 END_PROFILE(SMBecho);
2688 /****************************************************************************
2689 Reply to a printopen.
2690 ****************************************************************************/
2692 int reply_printopen(connection_struct *conn,
2693 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2697 START_PROFILE(SMBsplopen);
2699 if (!CAN_PRINT(conn)) {
2700 END_PROFILE(SMBsplopen);
2701 return ERROR_DOS(ERRDOS,ERRnoaccess);
2704 /* Open for exclusive use, write only. */
2705 fsp = print_fsp_open(conn, NULL);
2708 END_PROFILE(SMBsplopen);
2709 return(UNIXERROR(ERRDOS,ERRnoaccess));
2712 outsize = set_message(outbuf,1,0,True);
2713 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2715 DEBUG(3,("openprint fd=%d fnum=%d\n",
2716 fsp->fd, fsp->fnum));
2718 END_PROFILE(SMBsplopen);
2722 /****************************************************************************
2723 Reply to a printclose.
2724 ****************************************************************************/
2726 int reply_printclose(connection_struct *conn,
2727 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2729 int outsize = set_message(outbuf,0,0,True);
2730 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2732 START_PROFILE(SMBsplclose);
2734 CHECK_FSP(fsp,conn);
2736 if (!CAN_PRINT(conn)) {
2737 END_PROFILE(SMBsplclose);
2738 return ERROR_DOS(ERRDOS,ERRnoaccess);
2741 DEBUG(3,("printclose fd=%d fnum=%d\n",
2742 fsp->fd,fsp->fnum));
2744 close_err = close_file(fsp,True);
2746 if(close_err != 0) {
2748 END_PROFILE(SMBsplclose);
2749 return(UNIXERROR(ERRHRD,ERRgeneral));
2752 END_PROFILE(SMBsplclose);
2756 /****************************************************************************
2757 Reply to a printqueue.
2758 ****************************************************************************/
2760 int reply_printqueue(connection_struct *conn,
2761 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2763 int outsize = set_message(outbuf,2,3,True);
2764 int max_count = SVAL(inbuf,smb_vwv0);
2765 int start_index = SVAL(inbuf,smb_vwv1);
2766 START_PROFILE(SMBsplretq);
2768 /* we used to allow the client to get the cnum wrong, but that
2769 is really quite gross and only worked when there was only
2770 one printer - I think we should now only accept it if they
2771 get it right (tridge) */
2772 if (!CAN_PRINT(conn)) {
2773 END_PROFILE(SMBsplretq);
2774 return ERROR_DOS(ERRDOS,ERRnoaccess);
2777 SSVAL(outbuf,smb_vwv0,0);
2778 SSVAL(outbuf,smb_vwv1,0);
2779 SCVAL(smb_buf(outbuf),0,1);
2780 SSVAL(smb_buf(outbuf),1,0);
2782 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2783 start_index, max_count));
2786 print_queue_struct *queue = NULL;
2787 print_status_struct status;
2788 char *p = smb_buf(outbuf) + 3;
2789 int count = print_queue_status(SNUM(conn), &queue, &status);
2790 int num_to_get = ABS(max_count);
2791 int first = (max_count>0?start_index:start_index+max_count+1);
2797 num_to_get = MIN(num_to_get,count-first);
2800 for (i=first;i<first+num_to_get;i++) {
2801 put_dos_date2(p,0,queue[i].time);
2802 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2803 SSVAL(p,5, queue[i].job);
2804 SIVAL(p,7,queue[i].size);
2806 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2811 outsize = set_message(outbuf,2,28*count+3,False);
2812 SSVAL(outbuf,smb_vwv0,count);
2813 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2814 SCVAL(smb_buf(outbuf),0,1);
2815 SSVAL(smb_buf(outbuf),1,28*count);
2820 DEBUG(3,("%d entries returned in queue\n",count));
2823 END_PROFILE(SMBsplretq);
2827 /****************************************************************************
2828 Reply to a printwrite.
2829 ****************************************************************************/
2831 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2834 int outsize = set_message(outbuf,0,0,True);
2836 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2838 START_PROFILE(SMBsplwr);
2840 if (!CAN_PRINT(conn)) {
2841 END_PROFILE(SMBsplwr);
2842 return ERROR_DOS(ERRDOS,ERRnoaccess);
2845 CHECK_FSP(fsp,conn);
2848 numtowrite = SVAL(smb_buf(inbuf),1);
2849 data = smb_buf(inbuf) + 3;
2851 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2852 END_PROFILE(SMBsplwr);
2853 return(UNIXERROR(ERRHRD,ERRdiskfull));
2856 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2858 END_PROFILE(SMBsplwr);
2862 /****************************************************************************
2863 The guts of the mkdir command, split out so it may be called by the NT SMB
2865 ****************************************************************************/
2867 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2869 BOOL bad_path = False;
2870 SMB_STRUCT_STAT sbuf;
2873 unix_convert(directory,conn,0,&bad_path,&sbuf);
2875 if (ms_has_wild(directory)) {
2876 return NT_STATUS_OBJECT_NAME_INVALID;
2879 if (check_name(directory, conn))
2880 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
2883 NTSTATUS nterr = NT_STATUS_OK;
2884 if(errno == ENOENT) {
2885 unix_ERR_class = ERRDOS;
2887 unix_ERR_code = ERRbadpath;
2888 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2890 unix_ERR_code = ERRbadfile;
2891 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2894 if (!NT_STATUS_IS_OK(nterr))
2896 return map_nt_error_from_unix(errno);
2899 return NT_STATUS_OK;
2902 /****************************************************************************
2904 ****************************************************************************/
2906 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2911 START_PROFILE(SMBmkdir);
2913 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2915 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2917 status = mkdir_internal(conn, directory);
2918 if (!NT_STATUS_IS_OK(status))
2919 return ERROR_NT(status);
2921 outsize = set_message(outbuf,0,0,True);
2923 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2925 END_PROFILE(SMBmkdir);
2929 /****************************************************************************
2930 Static function used by reply_rmdir to delete an entire directory
2931 tree recursively. Return False on ok, True on fail.
2932 ****************************************************************************/
2934 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2936 const char *dname = NULL;
2938 void *dirptr = OpenDir(conn, directory, False);
2943 while((dname = ReadDirName(dirptr))) {
2947 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2950 /* Construct the full name. */
2951 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2957 pstrcpy(fullname, directory);
2958 pstrcat(fullname, "/");
2959 pstrcat(fullname, dname);
2961 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
2966 if(st.st_mode & S_IFDIR) {
2967 if(recursive_rmdir(conn, fullname)!=0) {
2971 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
2975 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
2984 /****************************************************************************
2985 The internals of the rmdir code - called elsewhere.
2986 ****************************************************************************/
2988 BOOL rmdir_internals(connection_struct *conn, char *directory)
2992 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
2993 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2995 * Check to see if the only thing in this directory are
2996 * vetoed files/directories. If so then delete them and
2997 * retry. If we fail to delete any of them (and we *don't*
2998 * do a recursive delete) then fail the rmdir.
3000 BOOL all_veto_files = True;
3002 void *dirptr = OpenDir(conn, directory, False);
3004 if(dirptr != NULL) {
3005 int dirpos = TellDir(dirptr);
3006 while ((dname = ReadDirName(dirptr))) {
3007 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3009 if(!IS_VETO_PATH(conn, dname)) {
3010 all_veto_files = False;
3015 if(all_veto_files) {
3016 SeekDir(dirptr,dirpos);
3017 while ((dname = ReadDirName(dirptr))) {
3021 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3024 /* Construct the full name. */
3025 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3030 pstrcpy(fullname, directory);
3031 pstrcat(fullname, "/");
3032 pstrcat(fullname, dname);
3034 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3036 if(st.st_mode & S_IFDIR) {
3037 if(lp_recursive_veto_delete(SNUM(conn))) {
3038 if(recursive_rmdir(conn, fullname) != 0)
3041 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3043 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3047 /* Retry the rmdir */
3048 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3058 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3063 /****************************************************************************
3065 ****************************************************************************/
3067 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3072 BOOL bad_path = False;
3073 SMB_STRUCT_STAT sbuf;
3074 START_PROFILE(SMBrmdir);
3076 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3078 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3080 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3082 if (check_name(directory,conn)) {
3083 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3084 ok = rmdir_internals(conn, directory);
3088 END_PROFILE(SMBrmdir);
3089 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3092 outsize = set_message(outbuf,0,0,True);
3094 DEBUG( 3, ( "rmdir %s\n", directory ) );
3096 END_PROFILE(SMBrmdir);
3100 /*******************************************************************
3101 Resolve wildcards in a filename rename.
3102 ********************************************************************/
3104 static BOOL resolve_wildcards(const char *name1, char *name2)
3106 fstring root1,root2;
3108 char *p,*p2, *pname1, *pname2;
3109 int available_space;
3112 pname1 = strrchr_m(name1,'/');
3113 pname2 = strrchr_m(name2,'/');
3115 if (!pname1 || !pname2)
3118 fstrcpy(root1,pname1);
3119 fstrcpy(root2,pname2);
3120 p = strrchr_m(root1,'.');
3127 p = strrchr_m(root2,'.');
3161 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3164 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3166 pstrcpy_base(pname2, root2, name2);
3172 /****************************************************************************
3173 Ensure open files have their names updates.
3174 ****************************************************************************/
3176 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3179 BOOL did_rename = False;
3181 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3182 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3183 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3184 fsp->fsp_name, newname ));
3185 string_set(&fsp->fsp_name, newname);
3190 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3191 (unsigned int)dev, (double)inode, newname ));
3194 /****************************************************************************
3195 Rename an open file - given an fsp.
3196 ****************************************************************************/
3198 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3200 SMB_STRUCT_STAT sbuf;
3201 BOOL bad_path = False;
3202 pstring newname_last_component;
3203 NTSTATUS error = NT_STATUS_OK;
3207 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3209 /* Ensure newname contains a '/' */
3210 if(strrchr_m(newname,'/') == 0) {
3213 pstrcpy(tmpstr, "./");
3214 pstrcat(tmpstr, newname);
3215 pstrcpy(newname, tmpstr);
3219 * Check for special case with case preserving and not
3220 * case sensitive. If the old last component differs from the original
3221 * last component only by case, then we should allow
3222 * the rename (user is trying to change the case of the
3226 if((case_sensitive == False) && (case_preserve == True) &&
3227 strequal(newname, fsp->fsp_name)) {
3229 pstring newname_modified_last_component;
3232 * Get the last component of the modified name.
3233 * Note that we guarantee that newname contains a '/'
3236 p = strrchr_m(newname,'/');
3237 pstrcpy(newname_modified_last_component,p+1);
3239 if(strcsequal(newname_modified_last_component,
3240 newname_last_component) == False) {
3242 * Replace the modified last component with
3245 pstrcpy(p+1, newname_last_component);
3250 * If the src and dest names are identical - including case,
3251 * don't do the rename, just return success.
3254 if (strcsequal(fsp->fsp_name, newname)) {
3255 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3257 return NT_STATUS_OK;
3260 dest_exists = vfs_object_exist(conn,newname,NULL);
3262 if(!replace_if_exists && dest_exists) {
3263 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3264 fsp->fsp_name,newname));
3265 return NT_STATUS_OBJECT_NAME_COLLISION;
3268 error = can_rename(newname,conn,&sbuf);
3270 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3271 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3272 nt_errstr(error), fsp->fsp_name,newname));
3273 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3274 error = NT_STATUS_ACCESS_DENIED;
3278 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3279 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3280 fsp->fsp_name,newname));
3281 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3282 return NT_STATUS_OK;
3285 if (errno == ENOTDIR || errno == EISDIR)
3286 error = NT_STATUS_OBJECT_NAME_COLLISION;
3288 error = map_nt_error_from_unix(errno);
3290 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3291 nt_errstr(error), fsp->fsp_name,newname));
3296 /****************************************************************************
3297 The guts of the rename command, split out so it may be called by the NT SMB
3299 ****************************************************************************/
3301 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3305 pstring newname_last_component;
3308 BOOL bad_path1 = False;
3309 BOOL bad_path2 = False;
3311 NTSTATUS error = NT_STATUS_OK;
3313 SMB_STRUCT_STAT sbuf1, sbuf2;
3315 *directory = *mask = 0;
3319 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3320 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3323 * Split the old name into directory and last component
3324 * strings. Note that unix_convert may have stripped off a
3325 * leading ./ from both name and newname if the rename is
3326 * at the root of the share. We need to make sure either both
3327 * name and newname contain a / character or neither of them do
3328 * as this is checked in resolve_wildcards().
3331 p = strrchr_m(name,'/');
3333 pstrcpy(directory,".");
3337 pstrcpy(directory,name);
3339 *p = '/'; /* Replace needed for exceptional test below. */
3343 * We should only check the mangled cache
3344 * here if unix_convert failed. This means
3345 * that the path in 'mask' doesn't exist
3346 * on the file system and so we need to look
3347 * for a possible mangle. This patch from
3348 * Tine Smukavec <valentin.smukavec@hermes.si>.
3351 if (!rc && mangle_is_mangled(mask))
3352 mangle_check_cache( mask );
3354 has_wild = ms_has_wild(mask);
3358 * No wildcards - just process the one file.
3360 BOOL is_short_name = mangle_is_8_3(name, True);
3362 /* Add a terminating '/' to the directory name. */
3363 pstrcat(directory,"/");
3364 pstrcat(directory,mask);
3366 /* Ensure newname contains a '/' also */
3367 if(strrchr_m(newname,'/') == 0) {
3370 pstrcpy(tmpstr, "./");
3371 pstrcat(tmpstr, newname);
3372 pstrcpy(newname, tmpstr);
3375 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3376 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3377 case_sensitive, case_preserve, short_case_preserve, directory,
3378 newname, newname_last_component, is_short_name));
3381 * Check for special case with case preserving and not
3382 * case sensitive, if directory and newname are identical,
3383 * and the old last component differs from the original
3384 * last component only by case, then we should allow
3385 * the rename (user is trying to change the case of the
3388 if((case_sensitive == False) &&
3389 (((case_preserve == True) &&
3390 (is_short_name == False)) ||
3391 ((short_case_preserve == True) &&
3392 (is_short_name == True))) &&
3393 strcsequal(directory, newname)) {
3394 pstring newname_modified_last_component;
3397 * Get the last component of the modified name.
3398 * Note that we guarantee that newname contains a '/'
3401 p = strrchr_m(newname,'/');
3402 pstrcpy(newname_modified_last_component,p+1);
3404 if(strcsequal(newname_modified_last_component,
3405 newname_last_component) == False) {
3407 * Replace the modified last component with
3410 pstrcpy(p+1, newname_last_component);
3414 resolve_wildcards(directory,newname);
3417 * The source object must exist.
3420 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3421 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3422 directory,newname));
3424 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3426 * Must return different errors depending on whether the parent
3427 * directory existed or not.
3430 p = strrchr_m(directory, '/');
3432 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3434 if (vfs_object_exist(conn, directory, NULL))
3435 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3436 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3438 error = map_nt_error_from_unix(errno);
3439 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3440 nt_errstr(error), directory,newname));
3445 error = can_rename(directory,conn,&sbuf1);
3447 if (!NT_STATUS_IS_OK(error)) {
3448 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3449 nt_errstr(error), directory,newname));
3454 * If the src and dest names are identical - including case,
3455 * don't do the rename, just return success.
3458 if (strcsequal(directory, newname)) {
3459 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3460 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3461 return NT_STATUS_OK;
3464 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3465 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3466 directory,newname));
3467 return NT_STATUS_OBJECT_NAME_COLLISION;
3470 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3471 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3472 directory,newname));
3473 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3474 return NT_STATUS_OK;
3477 if (errno == ENOTDIR || errno == EISDIR)
3478 error = NT_STATUS_OBJECT_NAME_COLLISION;
3480 error = map_nt_error_from_unix(errno);
3482 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3483 nt_errstr(error), directory,newname));
3488 * Wildcards - process each file that matches.
3490 void *dirptr = NULL;
3494 if (check_name(directory,conn))
3495 dirptr = OpenDir(conn, directory, True);
3498 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3500 if (strequal(mask,"????????.???"))
3503 while ((dname = ReadDirName(dirptr))) {
3506 pstrcpy(fname,dname);
3508 if(!mask_match(fname, mask, case_sensitive))
3511 error = NT_STATUS_ACCESS_DENIED;
3512 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3513 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3514 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3515 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3518 error = can_rename(fname,conn,&sbuf1);
3519 if (!NT_STATUS_IS_OK(error)) {
3520 DEBUG(6,("rename %s refused\n", fname));
3523 pstrcpy(destname,newname);
3525 if (!resolve_wildcards(fname,destname)) {
3526 DEBUG(6,("resolve_wildcards %s %s failed\n",
3531 if (!replace_if_exists &&
3532 vfs_file_exist(conn,destname, NULL)) {
3533 DEBUG(6,("file_exist %s\n", destname));
3534 error = NT_STATUS_OBJECT_NAME_COLLISION;
3538 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3539 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3542 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3548 if (count == 0 && NT_STATUS_IS_OK(error)) {
3549 error = map_nt_error_from_unix(errno);
3555 /****************************************************************************
3557 ****************************************************************************/
3559 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3568 START_PROFILE(SMBmv);
3570 p = smb_buf(inbuf) + 1;
3571 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3573 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3575 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3576 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3578 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3580 status = rename_internals(conn, name, newname, False);
3581 if (!NT_STATUS_IS_OK(status)) {
3582 return ERROR_NT(status);
3586 * Win2k needs a changenotify request response before it will
3587 * update after a rename..
3589 process_pending_change_notify_queue((time_t)0);
3590 outsize = set_message(outbuf,0,0,True);
3596 /*******************************************************************
3597 Copy a file as part of a reply_copy.
3598 ******************************************************************/
3600 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3601 int count,BOOL target_is_directory, int *err_ret)
3604 SMB_STRUCT_STAT src_sbuf, sbuf2;
3606 files_struct *fsp1,*fsp2;
3611 pstrcpy(dest,dest1);
3612 if (target_is_directory) {
3613 char *p = strrchr_m(src,'/');
3622 if (!vfs_file_exist(conn,src,&src_sbuf))
3625 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3626 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3631 if (!target_is_directory && count)
3632 ofun = FILE_EXISTS_OPEN;
3634 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3635 ZERO_STRUCTP(&sbuf2);
3637 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3638 ofun,src_sbuf.st_mode,0,&Access,&action);
3641 close_file(fsp1,False);
3645 if ((ofun&3) == 1) {
3646 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3647 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3649 * Stop the copy from occurring.
3652 src_sbuf.st_size = 0;
3656 if (src_sbuf.st_size)
3657 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3659 close_file(fsp1,False);
3661 /* Ensure the modtime is set correctly on the destination file. */
3662 fsp2->pending_modtime = src_sbuf.st_mtime;
3665 * As we are opening fsp1 read-only we only expect
3666 * an error on close on fsp2 if we are out of space.
3667 * Thus we don't look at the error return from the
3670 *err_ret = close_file(fsp2,False);
3672 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3675 /****************************************************************************
3676 Reply to a file copy.
3677 ****************************************************************************/
3679 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3684 pstring mask,newname;
3687 int error = ERRnoaccess;
3691 int tid2 = SVAL(inbuf,smb_vwv0);
3692 int ofun = SVAL(inbuf,smb_vwv1);
3693 int flags = SVAL(inbuf,smb_vwv2);
3694 BOOL target_is_directory=False;
3695 BOOL bad_path1 = False;
3696 BOOL bad_path2 = False;
3698 SMB_STRUCT_STAT sbuf1, sbuf2;
3700 START_PROFILE(SMBcopy);
3702 *directory = *mask = 0;
3705 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3706 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3708 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3710 if (tid2 != conn->cnum) {
3711 /* can't currently handle inter share copies XXXX */
3712 DEBUG(3,("Rejecting inter-share copy\n"));
3713 END_PROFILE(SMBcopy);
3714 return ERROR_DOS(ERRSRV,ERRinvdevice);
3717 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3718 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3720 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3721 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3723 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3725 if ((flags&1) && target_is_directory) {
3726 END_PROFILE(SMBcopy);
3727 return ERROR_DOS(ERRDOS,ERRbadfile);
3730 if ((flags&2) && !target_is_directory) {
3731 END_PROFILE(SMBcopy);
3732 return ERROR_DOS(ERRDOS,ERRbadpath);
3735 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3736 /* wants a tree copy! XXXX */
3737 DEBUG(3,("Rejecting tree copy\n"));
3738 END_PROFILE(SMBcopy);
3739 return ERROR_DOS(ERRSRV,ERRerror);
3742 p = strrchr_m(name,'/');
3744 pstrcpy(directory,"./");
3748 pstrcpy(directory,name);
3753 * We should only check the mangled cache
3754 * here if unix_convert failed. This means
3755 * that the path in 'mask' doesn't exist
3756 * on the file system and so we need to look
3757 * for a possible mangle. This patch from
3758 * Tine Smukavec <valentin.smukavec@hermes.si>.
3761 if (!rc && mangle_is_mangled(mask))
3762 mangle_check_cache( mask );
3764 has_wild = ms_has_wild(mask);
3767 pstrcat(directory,"/");
3768 pstrcat(directory,mask);
3769 if (resolve_wildcards(directory,newname) &&
3770 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3774 END_PROFILE(SMBcopy);
3775 return(UNIXERROR(ERRHRD,ERRgeneral));
3778 exists = vfs_file_exist(conn,directory,NULL);
3781 void *dirptr = NULL;
3785 if (check_name(directory,conn))
3786 dirptr = OpenDir(conn, directory, True);
3791 if (strequal(mask,"????????.???"))
3794 while ((dname = ReadDirName(dirptr))) {
3796 pstrcpy(fname,dname);
3798 if(!mask_match(fname, mask, case_sensitive))
3801 error = ERRnoaccess;
3802 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3803 pstrcpy(destname,newname);
3804 if (resolve_wildcards(fname,destname) &&
3805 copy_file(fname,destname,conn,ofun,
3806 count,target_is_directory,&err))
3808 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3816 /* Error on close... */
3818 END_PROFILE(SMBcopy);
3819 return(UNIXERROR(ERRHRD,ERRgeneral));
3823 END_PROFILE(SMBcopy);
3824 return ERROR_DOS(ERRDOS,error);
3826 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3827 unix_ERR_class = ERRDOS;
3828 unix_ERR_code = ERRbadpath;
3830 END_PROFILE(SMBcopy);
3831 return(UNIXERROR(ERRDOS,error));
3835 outsize = set_message(outbuf,1,0,True);
3836 SSVAL(outbuf,smb_vwv0,count);
3838 END_PROFILE(SMBcopy);
3842 /****************************************************************************
3844 ****************************************************************************/
3846 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3853 START_PROFILE(pathworks_setdir);
3856 if (!CAN_SETDIR(snum)) {
3857 END_PROFILE(pathworks_setdir);
3858 return ERROR_DOS(ERRDOS,ERRnoaccess);
3861 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3863 if (strlen(newdir) == 0) {
3866 ok = vfs_directory_exist(conn,newdir,NULL);
3868 string_set(&conn->connectpath,newdir);
3872 END_PROFILE(pathworks_setdir);
3873 return ERROR_DOS(ERRDOS,ERRbadpath);
3876 outsize = set_message(outbuf,0,0,True);
3877 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3879 DEBUG(3,("setdir %s\n", newdir));
3881 END_PROFILE(pathworks_setdir);
3885 /****************************************************************************
3886 Get a lock pid, dealing with large count requests.
3887 ****************************************************************************/
3889 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3891 if(!large_file_format)
3892 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3894 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3897 /****************************************************************************
3898 Get a lock count, dealing with large count requests.
3899 ****************************************************************************/
3901 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3903 SMB_BIG_UINT count = 0;
3905 if(!large_file_format) {
3906 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3909 #if defined(HAVE_LONGLONG)
3910 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3911 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3912 #else /* HAVE_LONGLONG */
3915 * NT4.x seems to be broken in that it sends large file (64 bit)
3916 * lockingX calls even if the CAP_LARGE_FILES was *not*
3917 * negotiated. For boxes without large unsigned ints truncate the
3918 * lock count by dropping the top 32 bits.
3921 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3922 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3923 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3924 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3925 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3928 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3929 #endif /* HAVE_LONGLONG */
3935 #if !defined(HAVE_LONGLONG)
3936 /****************************************************************************
3937 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3938 ****************************************************************************/
3940 static uint32 map_lock_offset(uint32 high, uint32 low)
3944 uint32 highcopy = high;
3947 * Try and find out how many significant bits there are in high.
3950 for(i = 0; highcopy; i++)
3954 * We use 31 bits not 32 here as POSIX
3955 * lock offsets may not be negative.
3958 mask = (~0) << (31 - i);
3961 return 0; /* Fail. */
3967 #endif /* !defined(HAVE_LONGLONG) */
3969 /****************************************************************************
3970 Get a lock offset, dealing with large offset requests.
3971 ****************************************************************************/
3973 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3975 SMB_BIG_UINT offset = 0;
3979 if(!large_file_format) {
3980 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3983 #if defined(HAVE_LONGLONG)
3984 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3985 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3986 #else /* HAVE_LONGLONG */
3989 * NT4.x seems to be broken in that it sends large file (64 bit)
3990 * lockingX calls even if the CAP_LARGE_FILES was *not*
3991 * negotiated. For boxes without large unsigned ints mangle the
3992 * lock offset by mapping the top 32 bits onto the lower 32.
3995 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3996 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3997 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4000 if((new_low = map_lock_offset(high, low)) == 0) {
4002 return (SMB_BIG_UINT)-1;
4005 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4006 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4007 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4008 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4011 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4012 #endif /* HAVE_LONGLONG */
4018 /****************************************************************************
4019 Reply to a lockingX request.
4020 ****************************************************************************/
4022 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4024 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4025 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4026 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4027 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4028 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4029 SMB_BIG_UINT count = 0, offset = 0;
4031 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4034 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4038 START_PROFILE(SMBlockingX);
4040 CHECK_FSP(fsp,conn);
4042 data = smb_buf(inbuf);
4044 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4045 /* we don't support these - and CANCEL_LOCK makes w2k
4046 and XP reboot so I don't really want to be
4047 compatible! (tridge) */
4048 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4051 /* Check if this is an oplock break on a file
4052 we have granted an oplock on.
4054 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4055 /* Client can insist on breaking to none. */
4056 BOOL break_to_none = (oplocklevel == 0);
4058 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4059 (unsigned int)oplocklevel, fsp->fnum ));
4062 * Make sure we have granted an exclusive or batch oplock on this file.
4065 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4066 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4067 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4069 /* if this is a pure oplock break request then don't send a reply */
4070 if (num_locks == 0 && num_ulocks == 0) {
4071 END_PROFILE(SMBlockingX);
4074 END_PROFILE(SMBlockingX);
4075 return ERROR_DOS(ERRDOS,ERRlock);
4079 if (remove_oplock(fsp, break_to_none) == False) {
4080 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4084 /* if this is a pure oplock break request then don't send a reply */
4085 if (num_locks == 0 && num_ulocks == 0) {
4086 /* Sanity check - ensure a pure oplock break is not a
4088 if(CVAL(inbuf,smb_vwv0) != 0xff)
4089 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4090 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4091 END_PROFILE(SMBlockingX);
4097 * We do this check *after* we have checked this is not a oplock break
4098 * response message. JRA.
4101 release_level_2_oplocks_on_change(fsp);
4103 /* Data now points at the beginning of the list
4104 of smb_unlkrng structs */
4105 for(i = 0; i < (int)num_ulocks; i++) {
4106 lock_pid = get_lock_pid( data, i, large_file_format);
4107 count = get_lock_count( data, i, large_file_format);
4108 offset = get_lock_offset( data, i, large_file_format, &err);
4111 * There is no error code marked "stupid client bug".... :-).
4114 END_PROFILE(SMBlockingX);
4115 return ERROR_DOS(ERRDOS,ERRnoaccess);
4118 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4119 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4121 status = do_unlock(fsp,conn,lock_pid,count,offset);
4122 if (NT_STATUS_V(status)) {
4123 END_PROFILE(SMBlockingX);
4124 return ERROR_NT(status);
4128 /* Setup the timeout in seconds. */
4130 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4132 /* Now do any requested locks */
4133 data += ((large_file_format ? 20 : 10)*num_ulocks);
4135 /* Data now points at the beginning of the list
4136 of smb_lkrng structs */
4138 for(i = 0; i < (int)num_locks; i++) {
4139 lock_pid = get_lock_pid( data, i, large_file_format);
4140 count = get_lock_count( data, i, large_file_format);
4141 offset = get_lock_offset( data, i, large_file_format, &err);
4144 * There is no error code marked "stupid client bug".... :-).
4147 END_PROFILE(SMBlockingX);
4148 return ERROR_DOS(ERRDOS,ERRnoaccess);
4151 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4152 (double)offset, (double)count, (unsigned int)lock_pid,
4153 fsp->fsp_name, (int)lock_timeout ));
4155 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4156 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4157 if (NT_STATUS_V(status)) {
4158 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4160 * A blocking lock was requested. Package up
4161 * this smb into a queued request and push it
4162 * onto the blocking lock queue.
4164 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4165 END_PROFILE(SMBlockingX);
4173 /* If any of the above locks failed, then we must unlock
4174 all of the previous locks (X/Open spec). */
4175 if (i != num_locks && num_locks != 0) {
4177 * Ensure we don't do a remove on the lock that just failed,
4178 * as under POSIX rules, if we have a lock already there, we
4179 * will delete it (and we shouldn't) .....
4181 for(i--; i >= 0; i--) {
4182 lock_pid = get_lock_pid( data, i, large_file_format);
4183 count = get_lock_count( data, i, large_file_format);
4184 offset = get_lock_offset( data, i, large_file_format, &err);
4187 * There is no error code marked "stupid client bug".... :-).
4190 END_PROFILE(SMBlockingX);
4191 return ERROR_DOS(ERRDOS,ERRnoaccess);
4194 do_unlock(fsp,conn,lock_pid,count,offset);
4196 END_PROFILE(SMBlockingX);
4197 return ERROR_NT(status);
4200 set_message(outbuf,2,0,True);
4202 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4203 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4205 END_PROFILE(SMBlockingX);
4206 return chain_reply(inbuf,outbuf,length,bufsize);
4209 /****************************************************************************
4210 Reply to a SMBreadbmpx (read block multiplex) request.
4211 ****************************************************************************/
4213 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4224 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4225 START_PROFILE(SMBreadBmpx);
4227 /* this function doesn't seem to work - disable by default */
4228 if (!lp_readbmpx()) {
4229 END_PROFILE(SMBreadBmpx);
4230 return ERROR_DOS(ERRSRV,ERRuseSTD);
4233 outsize = set_message(outbuf,8,0,True);
4235 CHECK_FSP(fsp,conn);
4238 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4239 maxcount = SVAL(inbuf,smb_vwv3);
4241 data = smb_buf(outbuf);
4242 pad = ((long)data)%4;
4247 max_per_packet = bufsize-(outsize+pad);
4251 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4252 END_PROFILE(SMBreadBmpx);
4253 return ERROR_DOS(ERRDOS,ERRlock);
4257 size_t N = MIN(max_per_packet,tcount-total_read);
4259 nread = read_file(fsp,data,startpos,N);
4264 if (nread < (ssize_t)N)
4265 tcount = total_read + nread;
4267 set_message(outbuf,8,nread,False);
4268 SIVAL(outbuf,smb_vwv0,startpos);
4269 SSVAL(outbuf,smb_vwv2,tcount);
4270 SSVAL(outbuf,smb_vwv6,nread);
4271 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4273 if (!send_smb(smbd_server_fd(),outbuf))
4274 exit_server("reply_readbmpx: send_smb failed.");
4276 total_read += nread;
4278 } while (total_read < (ssize_t)tcount);
4280 END_PROFILE(SMBreadBmpx);
4284 /****************************************************************************
4285 Reply to a SMBsetattrE.
4286 ****************************************************************************/
4288 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4290 struct utimbuf unix_times;
4292 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4293 START_PROFILE(SMBsetattrE);
4295 outsize = set_message(outbuf,0,0,True);
4297 if(!fsp || (fsp->conn != conn)) {
4298 END_PROFILE(SMBgetattrE);
4299 return ERROR_DOS(ERRDOS,ERRbadfid);
4303 * Convert the DOS times into unix times. Ignore create
4304 * time as UNIX can't set this.
4307 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4308 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4311 * Patch from Ray Frush <frush@engr.colostate.edu>
4312 * Sometimes times are sent as zero - ignore them.
4315 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4316 /* Ignore request */
4317 if( DEBUGLVL( 3 ) ) {
4318 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4319 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4321 END_PROFILE(SMBsetattrE);
4323 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4324 /* set modify time = to access time if modify time was 0 */
4325 unix_times.modtime = unix_times.actime;
4328 /* Set the date on this file */
4329 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4330 END_PROFILE(SMBsetattrE);
4331 return ERROR_DOS(ERRDOS,ERRnoaccess);
4334 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4335 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4337 END_PROFILE(SMBsetattrE);
4342 /* Back from the dead for OS/2..... JRA. */
4344 /****************************************************************************
4345 Reply to a SMBwritebmpx (write block multiplex primary) request.
4346 ****************************************************************************/
4348 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4351 ssize_t nwritten = -1;
4358 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4359 START_PROFILE(SMBwriteBmpx);
4361 CHECK_FSP(fsp,conn);
4365 tcount = SVAL(inbuf,smb_vwv1);
4366 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4367 write_through = BITSETW(inbuf+smb_vwv7,0);
4368 numtowrite = SVAL(inbuf,smb_vwv10);
4369 smb_doff = SVAL(inbuf,smb_vwv11);
4371 data = smb_base(inbuf) + smb_doff;
4373 /* If this fails we need to send an SMBwriteC response,
4374 not an SMBwritebmpx - set this up now so we don't forget */
4375 SCVAL(outbuf,smb_com,SMBwritec);
4377 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4378 END_PROFILE(SMBwriteBmpx);
4379 return(ERROR_DOS(ERRDOS,ERRlock));
4382 nwritten = write_file(fsp,data,startpos,numtowrite);
4384 if(lp_syncalways(SNUM(conn)) || write_through)
4385 sync_file(conn,fsp);
4387 if(nwritten < (ssize_t)numtowrite) {
4388 END_PROFILE(SMBwriteBmpx);
4389 return(UNIXERROR(ERRHRD,ERRdiskfull));
4392 /* If the maximum to be written to this file
4393 is greater than what we just wrote then set
4394 up a secondary struct to be attached to this
4395 fd, we will use this to cache error messages etc. */
4397 if((ssize_t)tcount > nwritten) {
4398 write_bmpx_struct *wbms;
4399 if(fsp->wbmpx_ptr != NULL)
4400 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4402 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4404 DEBUG(0,("Out of memory in reply_readmpx\n"));
4405 END_PROFILE(SMBwriteBmpx);
4406 return(ERROR_DOS(ERRSRV,ERRnoresource));
4408 wbms->wr_mode = write_through;
4409 wbms->wr_discard = False; /* No errors yet */
4410 wbms->wr_total_written = nwritten;
4411 wbms->wr_errclass = 0;
4413 fsp->wbmpx_ptr = wbms;
4416 /* We are returning successfully, set the message type back to
4418 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4420 outsize = set_message(outbuf,1,0,True);
4422 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4424 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4425 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4427 if (write_through && tcount==nwritten) {
4428 /* We need to send both a primary and a secondary response */
4429 smb_setlen(outbuf,outsize - 4);
4430 if (!send_smb(smbd_server_fd(),outbuf))
4431 exit_server("reply_writebmpx: send_smb failed.");
4433 /* Now the secondary */
4434 outsize = set_message(outbuf,1,0,True);
4435 SCVAL(outbuf,smb_com,SMBwritec);
4436 SSVAL(outbuf,smb_vwv0,nwritten);
4439 END_PROFILE(SMBwriteBmpx);
4443 /****************************************************************************
4444 Reply to a SMBwritebs (write block multiplex secondary) request.
4445 ****************************************************************************/
4447 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4450 ssize_t nwritten = -1;
4457 write_bmpx_struct *wbms;
4458 BOOL send_response = False;
4459 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4460 START_PROFILE(SMBwriteBs);
4462 CHECK_FSP(fsp,conn);
4465 tcount = SVAL(inbuf,smb_vwv1);
4466 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4467 numtowrite = SVAL(inbuf,smb_vwv6);
4468 smb_doff = SVAL(inbuf,smb_vwv7);
4470 data = smb_base(inbuf) + smb_doff;
4472 /* We need to send an SMBwriteC response, not an SMBwritebs */
4473 SCVAL(outbuf,smb_com,SMBwritec);
4475 /* This fd should have an auxiliary struct attached,
4476 check that it does */
4477 wbms = fsp->wbmpx_ptr;
4479 END_PROFILE(SMBwriteBs);
4483 /* If write through is set we can return errors, else we must cache them */
4484 write_through = wbms->wr_mode;
4486 /* Check for an earlier error */
4487 if(wbms->wr_discard) {
4488 END_PROFILE(SMBwriteBs);
4489 return -1; /* Just discard the packet */
4492 nwritten = write_file(fsp,data,startpos,numtowrite);
4494 if(lp_syncalways(SNUM(conn)) || write_through)
4495 sync_file(conn,fsp);
4497 if (nwritten < (ssize_t)numtowrite) {
4499 /* We are returning an error - we can delete the aux struct */
4502 fsp->wbmpx_ptr = NULL;
4503 END_PROFILE(SMBwriteBs);
4504 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4506 END_PROFILE(SMBwriteBs);
4507 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4510 /* Increment the total written, if this matches tcount
4511 we can discard the auxiliary struct (hurrah !) and return a writeC */
4512 wbms->wr_total_written += nwritten;
4513 if(wbms->wr_total_written >= tcount) {
4514 if (write_through) {
4515 outsize = set_message(outbuf,1,0,True);
4516 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4517 send_response = True;
4521 fsp->wbmpx_ptr = NULL;
4525 END_PROFILE(SMBwriteBs);
4529 END_PROFILE(SMBwriteBs);
4533 /****************************************************************************
4534 Reply to a SMBgetattrE.
4535 ****************************************************************************/
4537 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4539 SMB_STRUCT_STAT sbuf;
4542 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4543 START_PROFILE(SMBgetattrE);
4545 outsize = set_message(outbuf,11,0,True);
4547 if(!fsp || (fsp->conn != conn)) {
4548 END_PROFILE(SMBgetattrE);
4549 return ERROR_DOS(ERRDOS,ERRbadfid);
4552 /* Do an fstat on this file */
4553 if(fsp_stat(fsp, &sbuf)) {
4554 END_PROFILE(SMBgetattrE);
4555 return(UNIXERROR(ERRDOS,ERRnoaccess));
4558 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4561 * Convert the times into dos times. Set create
4562 * date to be last modify date as UNIX doesn't save
4566 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4567 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4568 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4571 SIVAL(outbuf,smb_vwv6,0);
4572 SIVAL(outbuf,smb_vwv8,0);
4574 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4575 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4576 SIVAL(outbuf,smb_vwv8,allocation_size);
4578 SSVAL(outbuf,smb_vwv10, mode);
4580 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4582 END_PROFILE(SMBgetattrE);