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 *exactly* the same way as W2K.
43 ****************************************************************************/
45 NTSTATUS check_path_syntax(const char *name)
47 while (*name == '\\' || *name == '/')
49 if (name[0] == '.' && name[1] == '\0')
50 return NT_STATUS_OBJECT_NAME_INVALID;
51 else if (name[0] == '.' && name[1] == '.' &&
52 (name[2] == '\\' || name [2] == '/' || name[2] == '\0'))
53 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
57 /****************************************************************************
58 Pull a string and check the path - provide for error return.
59 ****************************************************************************/
61 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, int flags, NTSTATUS *err)
63 size_t ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
64 *err = check_path_syntax(dest);
68 /****************************************************************************
69 Reply to a special message.
70 ****************************************************************************/
72 int reply_special(char *inbuf,char *outbuf)
75 int msg_type = CVAL(inbuf,0);
76 int msg_flags = CVAL(inbuf,1);
80 static BOOL already_got_session = False;
84 memset(outbuf,'\0',smb_size);
89 case 0x81: /* session request */
91 if (already_got_session) {
92 exit_server("multiple session request not permitted");
97 if (name_len(inbuf+4) > 50 ||
98 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
99 DEBUG(0,("Invalid name length in session request\n"));
102 name_extract(inbuf,4,name1);
103 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
104 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
107 set_local_machine_name(name1, True);
108 set_remote_machine_name(name2, True);
110 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
111 get_local_machine_name(), get_remote_machine_name(),
114 if (name_type == 'R') {
115 /* We are being asked for a pathworks session ---
117 SCVAL(outbuf, 0,0x83);
121 /* only add the client's machine name to the list
122 of possibly valid usernames if we are operating
123 in share mode security */
124 if (lp_security() == SEC_SHARE) {
125 add_session_user(get_remote_machine_name());
128 reload_services(True);
131 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
133 already_got_session = True;
136 case 0x89: /* session keepalive request
137 (some old clients produce this?) */
138 SCVAL(outbuf,0,SMBkeepalive);
142 case 0x82: /* positive session response */
143 case 0x83: /* negative session response */
144 case 0x84: /* retarget session response */
145 DEBUG(0,("Unexpected session response\n"));
148 case SMBkeepalive: /* session keepalive */
153 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
154 msg_type, msg_flags));
159 /****************************************************************************
161 ****************************************************************************/
163 int reply_tcon(connection_struct *conn,
164 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
171 uint16 vuid = SVAL(inbuf,smb_uid);
175 DATA_BLOB password_blob;
177 START_PROFILE(SMBtcon);
179 *service_buf = *password = *dev = 0;
181 p = smb_buf(inbuf)+1;
182 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
183 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
185 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
187 p = strrchr_m(service_buf,'\\');
191 service = service_buf;
194 password_blob = data_blob(password, pwlen+1);
196 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
198 data_blob_clear_free(&password_blob);
201 END_PROFILE(SMBtcon);
202 return ERROR_NT(nt_status);
205 outsize = set_message(outbuf,2,0,True);
206 SSVAL(outbuf,smb_vwv0,max_recv);
207 SSVAL(outbuf,smb_vwv1,conn->cnum);
208 SSVAL(outbuf,smb_tid,conn->cnum);
210 DEBUG(3,("tcon service=%s cnum=%d\n",
211 service, conn->cnum));
213 END_PROFILE(SMBtcon);
217 /****************************************************************************
218 Reply to a tcon and X.
219 ****************************************************************************/
221 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
226 /* what the cleint thinks the device is */
227 fstring client_devicetype;
228 /* what the server tells the client the share represents */
229 const char *server_devicetype;
231 uint16 vuid = SVAL(inbuf,smb_uid);
232 int passlen = SVAL(inbuf,smb_vwv3);
235 extern BOOL global_encrypted_passwords_negotiated;
237 START_PROFILE(SMBtconX);
239 *service = *client_devicetype = 0;
241 /* we might have to close an old one */
242 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
243 close_cnum(conn,vuid);
246 if (passlen > MAX_PASS_LEN) {
247 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
250 if (global_encrypted_passwords_negotiated) {
251 password = data_blob(smb_buf(inbuf),passlen);
253 password = data_blob(smb_buf(inbuf),passlen+1);
254 /* Ensure correct termination */
255 password.data[passlen]=0;
258 p = smb_buf(inbuf) + passlen;
259 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
262 * the service name can be either: \\server\share
263 * or share directly like on the DELL PowerVault 705
266 q = strchr_m(path+2,'\\');
268 END_PROFILE(SMBtconX);
269 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
271 fstrcpy(service,q+1);
274 fstrcpy(service,path);
276 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
278 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
280 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
282 data_blob_clear_free(&password);
285 END_PROFILE(SMBtconX);
286 return ERROR_NT(nt_status);
290 server_devicetype = "IPC";
291 else if ( IS_PRINT(conn) )
292 server_devicetype = "LPT1:";
294 server_devicetype = "A:";
296 if (Protocol < PROTOCOL_NT1) {
297 set_message(outbuf,2,0,True);
299 p += srvstr_push(outbuf, p, server_devicetype, -1,
300 STR_TERMINATE|STR_ASCII);
301 set_message_end(outbuf,p);
303 /* NT sets the fstype of IPC$ to the null string */
304 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
306 set_message(outbuf,3,0,True);
309 p += srvstr_push(outbuf, p, server_devicetype, -1,
310 STR_TERMINATE|STR_ASCII);
311 p += srvstr_push(outbuf, p, fstype, -1,
314 set_message_end(outbuf,p);
316 /* what does setting this bit do? It is set by NT4 and
317 may affect the ability to autorun mounted cdroms */
318 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
319 (lp_csc_policy(SNUM(conn)) << 2));
321 init_dfsroot(conn, inbuf, outbuf);
325 DEBUG(3,("tconX service=%s \n",
328 /* set the incoming and outgoing tid to the just created one */
329 SSVAL(inbuf,smb_tid,conn->cnum);
330 SSVAL(outbuf,smb_tid,conn->cnum);
332 END_PROFILE(SMBtconX);
333 return chain_reply(inbuf,outbuf,length,bufsize);
336 /****************************************************************************
337 Reply to an unknown type.
338 ****************************************************************************/
340 int reply_unknown(char *inbuf,char *outbuf)
343 type = CVAL(inbuf,smb_com);
345 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
346 smb_fn_name(type), type, type));
348 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
351 /****************************************************************************
353 ****************************************************************************/
355 int reply_ioctl(connection_struct *conn,
356 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
358 uint16 device = SVAL(inbuf,smb_vwv1);
359 uint16 function = SVAL(inbuf,smb_vwv2);
360 uint32 ioctl_code = (device << 16) + function;
361 int replysize, outsize;
363 START_PROFILE(SMBioctl);
365 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
367 switch (ioctl_code) {
368 case IOCTL_QUERY_JOB_INFO:
372 END_PROFILE(SMBioctl);
373 return(ERROR_DOS(ERRSRV,ERRnosupport));
376 outsize = set_message(outbuf,8,replysize+1,True);
377 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
378 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
379 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
380 p = smb_buf(outbuf) + 1; /* Allow for alignment */
382 switch (ioctl_code) {
383 case IOCTL_QUERY_JOB_INFO:
385 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
387 END_PROFILE(SMBioctl);
388 return(UNIXERROR(ERRDOS,ERRbadfid));
390 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
391 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
392 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
397 END_PROFILE(SMBioctl);
401 /****************************************************************************
403 ****************************************************************************/
405 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
411 BOOL bad_path = False;
412 SMB_STRUCT_STAT sbuf;
415 START_PROFILE(SMBchkpth);
417 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE, &status);
418 if (!NT_STATUS_IS_OK(status)) {
419 END_PROFILE(SMBchkpth);
420 return ERROR_NT(status);
423 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
425 unix_convert(name,conn,0,&bad_path,&sbuf);
427 mode = SVAL(inbuf,smb_vwv0);
429 if (check_name(name,conn)) {
430 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
431 if (!(ok = S_ISDIR(sbuf.st_mode))) {
432 END_PROFILE(SMBchkpth);
433 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
438 /* We special case this - as when a Windows machine
439 is parsing a path is steps through the components
440 one at a time - if a component fails it expects
441 ERRbadpath, not ERRbadfile.
443 if(errno == ENOENT) {
445 * Windows returns different error codes if
446 * the parent directory is valid but not the
447 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
448 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
449 * if the path is invalid.
452 END_PROFILE(SMBchkpth);
453 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
455 END_PROFILE(SMBchkpth);
456 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
458 } else if (errno == ENOTDIR) {
459 END_PROFILE(SMBchkpth);
460 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
463 END_PROFILE(SMBchkpth);
464 return(UNIXERROR(ERRDOS,ERRbadpath));
467 outsize = set_message(outbuf,0,0,True);
469 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
471 END_PROFILE(SMBchkpth);
475 /****************************************************************************
477 ****************************************************************************/
479 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
483 SMB_STRUCT_STAT sbuf;
488 BOOL bad_path = False;
492 START_PROFILE(SMBgetatr);
494 p = smb_buf(inbuf) + 1;
495 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
496 if (!NT_STATUS_IS_OK(status)) {
497 END_PROFILE(SMBgetatr);
498 return ERROR_NT(status);
501 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
503 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
504 under WfWg - weird! */
506 mode = aHIDDEN | aDIR;
507 if (!CAN_WRITE(conn))
513 unix_convert(fname,conn,0,&bad_path,&sbuf);
514 if (check_name(fname,conn)) {
515 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
516 mode = dos_mode(conn,fname,&sbuf);
518 mtime = sbuf.st_mtime;
523 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
529 END_PROFILE(SMBgetatr);
530 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
533 outsize = set_message(outbuf,10,0,True);
535 SSVAL(outbuf,smb_vwv0,mode);
536 if(lp_dos_filetime_resolution(SNUM(conn)) )
537 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
539 put_dos_date3(outbuf,smb_vwv1,mtime);
540 SIVAL(outbuf,smb_vwv3,(uint32)size);
542 if (Protocol >= PROTOCOL_NT1)
543 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
545 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
547 END_PROFILE(SMBgetatr);
551 /****************************************************************************
553 ****************************************************************************/
555 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
562 SMB_STRUCT_STAT sbuf;
563 BOOL bad_path = False;
567 START_PROFILE(SMBsetatr);
569 p = smb_buf(inbuf) + 1;
570 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
571 if (!NT_STATUS_IS_OK(status)) {
572 END_PROFILE(SMBsetatr);
573 return ERROR_NT(status);
576 unix_convert(fname,conn,0,&bad_path,&sbuf);
578 mode = SVAL(inbuf,smb_vwv0);
579 mtime = make_unix_date3(inbuf+smb_vwv1);
581 if (mode != FILE_ATTRIBUTE_NORMAL) {
582 if (VALID_STAT_OF_DIR(sbuf))
587 if (check_name(fname,conn))
588 ok = (file_chmod(conn,fname,mode,NULL) == 0);
594 ok = set_filetime(conn,fname,mtime);
597 END_PROFILE(SMBsetatr);
598 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
601 outsize = set_message(outbuf,0,0,True);
603 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
605 END_PROFILE(SMBsetatr);
609 /****************************************************************************
611 ****************************************************************************/
613 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
616 SMB_BIG_UINT dfree,dsize,bsize;
617 START_PROFILE(SMBdskattr);
619 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
621 outsize = set_message(outbuf,5,0,True);
623 if (Protocol <= PROTOCOL_LANMAN2) {
624 double total_space, free_space;
625 /* we need to scale this to a number that DOS6 can handle. We
626 use floating point so we can handle large drives on systems
627 that don't have 64 bit integers
629 we end up displaying a maximum of 2G to DOS systems
631 total_space = dsize * (double)bsize;
632 free_space = dfree * (double)bsize;
634 dsize = (total_space+63*512) / (64*512);
635 dfree = (free_space+63*512) / (64*512);
637 if (dsize > 0xFFFF) dsize = 0xFFFF;
638 if (dfree > 0xFFFF) dfree = 0xFFFF;
640 SSVAL(outbuf,smb_vwv0,dsize);
641 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
642 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
643 SSVAL(outbuf,smb_vwv3,dfree);
645 SSVAL(outbuf,smb_vwv0,dsize);
646 SSVAL(outbuf,smb_vwv1,bsize/512);
647 SSVAL(outbuf,smb_vwv2,512);
648 SSVAL(outbuf,smb_vwv3,dfree);
651 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
653 END_PROFILE(SMBdskattr);
657 /****************************************************************************
659 Can be called from SMBsearch, SMBffirst or SMBfunique.
660 ****************************************************************************/
662 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
672 unsigned int numentries = 0;
673 unsigned int maxentries = 0;
674 BOOL finished = False;
681 BOOL check_descend = False;
682 BOOL expect_close = False;
683 BOOL can_open = True;
684 BOOL bad_path = False;
686 START_PROFILE(SMBsearch);
688 *mask = *directory = *fname = 0;
690 /* If we were called as SMBffirst then we must expect close. */
691 if(CVAL(inbuf,smb_com) == SMBffirst)
694 outsize = set_message(outbuf,1,3,True);
695 maxentries = SVAL(inbuf,smb_vwv0);
696 dirtype = SVAL(inbuf,smb_vwv1);
697 p = smb_buf(inbuf) + 1;
698 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status);
699 if (!NT_STATUS_IS_OK(nt_status)) {
700 END_PROFILE(SMBsearch);
701 return ERROR_NT(nt_status);
704 status_len = SVAL(p, 0);
707 /* dirtype &= ~aDIR; */
709 if (status_len == 0) {
710 SMB_STRUCT_STAT sbuf;
713 pstrcpy(directory,path);
715 unix_convert(directory,conn,0,&bad_path,&sbuf);
718 if (!check_name(directory,conn))
721 p = strrchr_m(dir2,'/');
730 p = strrchr_m(directory,'/');
736 if (strlen(directory) == 0)
737 pstrcpy(directory,".");
738 memset((char *)status,'\0',21);
739 SCVAL(status,0,(dirtype & 0x1F));
744 status_dirtype = CVAL(status,0) & 0x1F;
745 if (status_dirtype != (dirtype & 0x1F))
746 dirtype = status_dirtype;
748 conn->dirptr = dptr_fetch(status+12,&dptr_num);
751 string_set(&conn->dirpath,dptr_path(dptr_num));
752 pstrcpy(mask, dptr_wcard(dptr_num));
756 p = smb_buf(outbuf) + 3;
759 if (status_len == 0) {
760 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
763 END_PROFILE(SMBsearch);
764 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
766 END_PROFILE(SMBsearch);
767 return ERROR_DOS(ERRDOS,ERRnofids);
769 dptr_set_wcard(dptr_num, strdup(mask));
770 dptr_set_attr(dptr_num, dirtype);
772 dirtype = dptr_attr(dptr_num);
775 DEBUG(4,("dptr_num is %d\n",dptr_num));
778 if ((dirtype&0x1F) == aVOLID) {
780 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
781 dptr_fill(p+12,dptr_num);
782 if (dptr_zero(p+12) && (status_len==0))
786 p += DIR_STRUCT_SIZE;
789 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
791 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
792 conn->dirpath,lp_dontdescend(SNUM(conn))));
793 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
794 check_descend = True;
796 for (i=numentries;(i<maxentries) && !finished;i++) {
797 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
800 make_dir_struct(p,mask,fname,size,mode,date);
801 dptr_fill(p+12,dptr_num);
804 p += DIR_STRUCT_SIZE;
813 /* If we were called as SMBffirst with smb_search_id == NULL
814 and no entries were found then return error and close dirptr
817 if(ok && expect_close && numentries == 0 && status_len == 0) {
818 if (Protocol < PROTOCOL_NT1) {
819 SCVAL(outbuf,smb_rcls,ERRDOS);
820 SSVAL(outbuf,smb_err,ERRnofiles);
822 /* Also close the dptr - we know it's gone */
823 dptr_close(&dptr_num);
824 } else if (numentries == 0 || !ok) {
825 if (Protocol < PROTOCOL_NT1) {
826 SCVAL(outbuf,smb_rcls,ERRDOS);
827 SSVAL(outbuf,smb_err,ERRnofiles);
829 dptr_close(&dptr_num);
832 /* If we were called as SMBfunique, then we can close the dirptr now ! */
833 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
834 dptr_close(&dptr_num);
836 SSVAL(outbuf,smb_vwv0,numentries);
837 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
838 SCVAL(smb_buf(outbuf),0,5);
839 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
841 if (Protocol >= PROTOCOL_NT1)
842 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
844 outsize += DIR_STRUCT_SIZE*numentries;
845 smb_setlen(outbuf,outsize - 4);
847 if ((! *directory) && dptr_path(dptr_num))
848 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
850 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
851 smb_fn_name(CVAL(inbuf,smb_com)),
852 mask, directory, dirtype, numentries, maxentries ) );
854 END_PROFILE(SMBsearch);
858 /****************************************************************************
859 Reply to a fclose (stop directory search).
860 ****************************************************************************/
862 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
872 START_PROFILE(SMBfclose);
874 outsize = set_message(outbuf,1,0,True);
875 p = smb_buf(inbuf) + 1;
876 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err);
877 if (!NT_STATUS_IS_OK(err)) {
878 END_PROFILE(SMBfclose);
879 return ERROR_NT(err);
882 status_len = SVAL(p,0);
885 if (status_len == 0) {
886 END_PROFILE(SMBfclose);
887 return ERROR_DOS(ERRSRV,ERRsrverror);
892 if(dptr_fetch(status+12,&dptr_num)) {
893 /* Close the dptr - we know it's gone */
894 dptr_close(&dptr_num);
897 SSVAL(outbuf,smb_vwv0,0);
899 DEBUG(3,("search close\n"));
901 END_PROFILE(SMBfclose);
905 /****************************************************************************
907 ****************************************************************************/
909 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
919 SMB_STRUCT_STAT sbuf;
920 BOOL bad_path = False;
922 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
924 START_PROFILE(SMBopen);
926 share_mode = SVAL(inbuf,smb_vwv0);
928 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
929 if (!NT_STATUS_IS_OK(status)) {
930 END_PROFILE(SMBopen);
931 return ERROR_NT(status);
934 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
936 unix_convert(fname,conn,0,&bad_path,&sbuf);
938 unixmode = unix_mode(conn,aARCH,fname);
940 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
941 unixmode, oplock_request,&rmode,NULL);
944 END_PROFILE(SMBopen);
945 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
949 fmode = dos_mode(conn,fname,&sbuf);
950 mtime = sbuf.st_mtime;
953 DEBUG(3,("attempt to open a directory %s\n",fname));
954 close_file(fsp,False);
955 END_PROFILE(SMBopen);
956 return ERROR_DOS(ERRDOS,ERRnoaccess);
959 outsize = set_message(outbuf,7,0,True);
960 SSVAL(outbuf,smb_vwv0,fsp->fnum);
961 SSVAL(outbuf,smb_vwv1,fmode);
962 if(lp_dos_filetime_resolution(SNUM(conn)) )
963 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
965 put_dos_date3(outbuf,smb_vwv2,mtime);
966 SIVAL(outbuf,smb_vwv4,(uint32)size);
967 SSVAL(outbuf,smb_vwv6,rmode);
969 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
970 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
972 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
973 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
974 END_PROFILE(SMBopen);
978 /****************************************************************************
979 Reply to an open and X.
980 ****************************************************************************/
982 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
985 int smb_mode = SVAL(inbuf,smb_vwv3);
986 int smb_attr = SVAL(inbuf,smb_vwv5);
987 /* Breakout the oplock request bits so we can set the
988 reply bits separately. */
989 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
990 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
991 BOOL oplock_request = ex_oplock_request | core_oplock_request;
993 int open_flags = SVAL(inbuf,smb_vwv2);
994 int smb_sattr = SVAL(inbuf,smb_vwv4);
995 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
997 int smb_ofun = SVAL(inbuf,smb_vwv8);
1000 int fmode=0,mtime=0,rmode=0;
1001 SMB_STRUCT_STAT sbuf;
1003 BOOL bad_path = False;
1006 START_PROFILE(SMBopenX);
1008 /* If it's an IPC, pass off the pipe handler. */
1010 if (lp_nt_pipe_support()) {
1011 END_PROFILE(SMBopenX);
1012 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1014 END_PROFILE(SMBopenX);
1015 return ERROR_DOS(ERRSRV,ERRaccess);
1019 /* XXXX we need to handle passed times, sattr and flags */
1020 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
1021 if (!NT_STATUS_IS_OK(status)) {
1022 END_PROFILE(SMBopenX);
1023 return ERROR_NT(status);
1026 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1028 unix_convert(fname,conn,0,&bad_path,&sbuf);
1030 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1032 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1033 oplock_request, &rmode,&smb_action);
1036 END_PROFILE(SMBopenX);
1037 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1040 size = sbuf.st_size;
1041 fmode = dos_mode(conn,fname,&sbuf);
1042 mtime = sbuf.st_mtime;
1044 close_file(fsp,False);
1045 END_PROFILE(SMBopenX);
1046 return ERROR_DOS(ERRDOS,ERRnoaccess);
1049 /* If the caller set the extended oplock request bit
1050 and we granted one (by whatever means) - set the
1051 correct bit for extended oplock reply.
1054 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1055 smb_action |= EXTENDED_OPLOCK_GRANTED;
1057 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1058 smb_action |= EXTENDED_OPLOCK_GRANTED;
1060 /* If the caller set the core oplock request bit
1061 and we granted one (by whatever means) - set the
1062 correct bit for core oplock reply.
1065 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1066 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1068 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1069 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1071 set_message(outbuf,15,0,True);
1072 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1073 SSVAL(outbuf,smb_vwv3,fmode);
1074 if(lp_dos_filetime_resolution(SNUM(conn)) )
1075 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1077 put_dos_date3(outbuf,smb_vwv4,mtime);
1078 SIVAL(outbuf,smb_vwv6,(uint32)size);
1079 SSVAL(outbuf,smb_vwv8,rmode);
1080 SSVAL(outbuf,smb_vwv11,smb_action);
1082 END_PROFILE(SMBopenX);
1083 return chain_reply(inbuf,outbuf,length,bufsize);
1086 /****************************************************************************
1087 Reply to a SMBulogoffX.
1088 ****************************************************************************/
1090 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1092 uint16 vuid = SVAL(inbuf,smb_uid);
1093 user_struct *vuser = get_valid_user_struct(vuid);
1094 START_PROFILE(SMBulogoffX);
1097 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1099 /* in user level security we are supposed to close any files
1100 open by this user */
1101 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1102 file_close_user(vuid);
1104 invalidate_vuid(vuid);
1106 set_message(outbuf,2,0,True);
1108 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1110 END_PROFILE(SMBulogoffX);
1111 return chain_reply(inbuf,outbuf,length,bufsize);
1114 /****************************************************************************
1115 Reply to a mknew or a create.
1116 ****************************************************************************/
1118 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1126 BOOL bad_path = False;
1128 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1129 SMB_STRUCT_STAT sbuf;
1131 START_PROFILE(SMBcreate);
1133 com = SVAL(inbuf,smb_com);
1135 createmode = SVAL(inbuf,smb_vwv0);
1136 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status);
1137 if (!NT_STATUS_IS_OK(status)) {
1138 END_PROFILE(SMBcreate);
1139 return ERROR_NT(status);
1142 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1144 unix_convert(fname,conn,0,&bad_path,&sbuf);
1146 if (createmode & aVOLID)
1147 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1149 unixmode = unix_mode(conn,createmode,fname);
1151 if(com == SMBmknew) {
1152 /* We should fail if file exists. */
1153 ofun = FILE_CREATE_IF_NOT_EXIST;
1155 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1156 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1159 /* Open file in dos compatibility share mode. */
1160 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1161 ofun, unixmode, oplock_request, NULL, NULL);
1164 END_PROFILE(SMBcreate);
1165 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1168 outsize = set_message(outbuf,1,0,True);
1169 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1171 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1172 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1174 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1175 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1177 DEBUG( 2, ( "new file %s\n", fname ) );
1178 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1180 END_PROFILE(SMBcreate);
1184 /****************************************************************************
1185 Reply to a create temporary file.
1186 ****************************************************************************/
1188 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1194 BOOL bad_path = False;
1196 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1198 SMB_STRUCT_STAT sbuf;
1202 START_PROFILE(SMBctemp);
1204 createmode = SVAL(inbuf,smb_vwv0);
1205 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
1206 if (!NT_STATUS_IS_OK(status)) {
1207 END_PROFILE(SMBctemp);
1208 return ERROR_NT(status);
1210 pstrcat(fname,"\\TMXXXXXX");
1212 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1214 unix_convert(fname,conn,0,&bad_path,&sbuf);
1216 unixmode = unix_mode(conn,createmode,fname);
1218 tmpfd = smb_mkstemp(fname);
1220 END_PROFILE(SMBctemp);
1221 return(UNIXERROR(ERRDOS,ERRnoaccess));
1224 SMB_VFS_STAT(conn,fname,&sbuf);
1226 /* Open file in dos compatibility share mode. */
1227 /* We should fail if file does not exist. */
1228 fsp = open_file_shared(conn,fname,&sbuf,
1229 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1230 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1231 unixmode, oplock_request, NULL, NULL);
1233 /* close fd from smb_mkstemp() */
1237 END_PROFILE(SMBctemp);
1238 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1241 outsize = set_message(outbuf,1,0,True);
1242 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1244 /* the returned filename is relative to the directory */
1245 s = strrchr_m(fname, '/');
1251 p = smb_buf(outbuf);
1252 SSVALS(p, 0, -1); /* what is this? not in spec */
1253 SSVAL(p, 2, strlen(s));
1255 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1256 outsize = set_message_end(outbuf, p);
1258 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1259 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1261 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1262 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1264 DEBUG( 2, ( "created temp file %s\n", fname ) );
1265 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1266 fname, fsp->fd, createmode, (int)unixmode ) );
1268 END_PROFILE(SMBctemp);
1272 /*******************************************************************
1273 Check if a user is allowed to rename a file.
1274 ********************************************************************/
1276 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1282 if (!CAN_WRITE(conn))
1283 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1285 if (S_ISDIR(pst->st_mode))
1286 return NT_STATUS_OK;
1288 /* We need a better way to return NT status codes from open... */
1292 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1293 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1296 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1297 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1298 ret = NT_STATUS_SHARING_VIOLATION;
1301 unix_ERR_ntstatus = NT_STATUS_OK;
1304 close_file(fsp,False);
1305 return NT_STATUS_OK;
1308 /*******************************************************************
1309 Check if a user is allowed to delete a file.
1310 ********************************************************************/
1312 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1314 SMB_STRUCT_STAT sbuf;
1320 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1323 if (!CAN_WRITE(conn))
1324 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1326 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1327 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1329 fmode = dos_mode(conn,fname,&sbuf);
1331 /* Can't delete a directory. */
1333 return NT_STATUS_FILE_IS_A_DIRECTORY;
1335 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1336 return NT_STATUS_OBJECT_NAME_INVALID;
1337 #endif /* JRATEST */
1339 if (!lp_delete_readonly(SNUM(conn))) {
1341 return NT_STATUS_CANNOT_DELETE;
1343 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1344 return NT_STATUS_NO_SUCH_FILE;
1346 /* We need a better way to return NT status codes from open... */
1350 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1351 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1354 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1355 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1356 ret = unix_ERR_ntstatus;
1357 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1358 ret = NT_STATUS_SHARING_VIOLATION;
1361 unix_ERR_ntstatus = NT_STATUS_OK;
1364 close_file(fsp,False);
1365 return NT_STATUS_OK;
1368 /****************************************************************************
1369 The guts of the unlink command, split out so it may be called by the NT SMB
1371 ****************************************************************************/
1373 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1379 NTSTATUS error = NT_STATUS_OK;
1381 BOOL bad_path = False;
1383 SMB_STRUCT_STAT sbuf;
1385 *directory = *mask = 0;
1387 /* We must check for wildcards in the name given
1388 * directly by the client - before any unmangling.
1389 * This prevents an unmangling of a UNIX name containing
1390 * a DOS wildcard like '*' or '?' from unmangling into
1391 * a wildcard delete which was not intended.
1392 * FIX for #226. JRA.
1395 has_wild = ms_has_wild(name);
1397 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1399 p = strrchr_m(name,'/');
1401 pstrcpy(directory,".");
1405 pstrcpy(directory,name);
1410 * We should only check the mangled cache
1411 * here if unix_convert failed. This means
1412 * that the path in 'mask' doesn't exist
1413 * on the file system and so we need to look
1414 * for a possible mangle. This patch from
1415 * Tine Smukavec <valentin.smukavec@hermes.si>.
1418 if (!rc && mangle_is_mangled(mask))
1419 mangle_check_cache( mask );
1422 pstrcat(directory,"/");
1423 pstrcat(directory,mask);
1424 error = can_delete(directory,conn,dirtype);
1425 if (!NT_STATUS_IS_OK(error))
1428 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1432 void *dirptr = NULL;
1435 if (check_name(directory,conn))
1436 dirptr = OpenDir(conn, directory, True);
1438 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1439 the pattern matches against the long name, otherwise the short name
1440 We don't implement this yet XXXX
1444 error = NT_STATUS_NO_SUCH_FILE;
1446 if (strequal(mask,"????????.???"))
1449 while ((dname = ReadDirName(dirptr))) {
1451 pstrcpy(fname,dname);
1453 if(!mask_match(fname, mask, case_sensitive))
1456 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1457 error = can_delete(fname,conn,dirtype);
1458 if (!NT_STATUS_IS_OK(error))
1460 if (SMB_VFS_UNLINK(conn,fname) == 0)
1462 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1468 if (count == 0 && NT_STATUS_IS_OK(error)) {
1469 error = map_nt_error_from_unix(errno);
1475 /****************************************************************************
1477 ****************************************************************************/
1479 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1486 START_PROFILE(SMBunlink);
1488 dirtype = SVAL(inbuf,smb_vwv0);
1490 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 END_PROFILE(SMBunlink);
1493 return ERROR_NT(status);
1496 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1498 DEBUG(3,("reply_unlink : %s\n",name));
1500 status = unlink_internals(conn, dirtype, name);
1501 if (!NT_STATUS_IS_OK(status))
1502 return ERROR_NT(status);
1505 * Win2k needs a changenotify request response before it will
1506 * update after a rename..
1508 process_pending_change_notify_queue((time_t)0);
1510 outsize = set_message(outbuf,0,0,True);
1512 END_PROFILE(SMBunlink);
1516 /****************************************************************************
1518 ****************************************************************************/
1520 void fail_readraw(void)
1523 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1525 exit_server(errstr);
1528 /****************************************************************************
1529 Use sendfile in readbraw.
1530 ****************************************************************************/
1532 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1533 ssize_t mincount, char *outbuf)
1537 #if defined(WITH_SENDFILE)
1539 * We can only use sendfile on a non-chained packet and on a file
1540 * that is exclusively oplocked. reply_readbraw has already checked the length.
1543 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1544 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1547 _smb_setlen(outbuf,nread);
1548 header.data = outbuf;
1552 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1554 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1555 * return ENOSYS then pretend we just got a normal read.
1557 if (errno == ENOSYS)
1560 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1561 fsp->fsp_name, strerror(errno) ));
1562 exit_server("send_file_readbraw sendfile failed");
1571 ret = read_file(fsp,outbuf+4,startpos,nread);
1572 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1581 _smb_setlen(outbuf,ret);
1582 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1586 /****************************************************************************
1587 Reply to a readbraw (core+ protocol).
1588 ****************************************************************************/
1590 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1592 extern struct current_user current_user;
1593 ssize_t maxcount,mincount;
1596 char *header = outbuf;
1598 START_PROFILE(SMBreadbraw);
1600 if (srv_is_signing_active()) {
1601 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1605 * Special check if an oplock break has been issued
1606 * and the readraw request croses on the wire, we must
1607 * return a zero length response here.
1610 if(global_oplock_break) {
1611 _smb_setlen(header,0);
1612 if (write_data(smbd_server_fd(),header,4) != 4)
1614 DEBUG(5,("readbraw - oplock break finished\n"));
1615 END_PROFILE(SMBreadbraw);
1619 fsp = file_fsp(inbuf,smb_vwv0);
1621 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1623 * fsp could be NULL here so use the value from the packet. JRA.
1625 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1626 _smb_setlen(header,0);
1627 if (write_data(smbd_server_fd(),header,4) != 4)
1629 END_PROFILE(SMBreadbraw);
1633 CHECK_FSP(fsp,conn);
1635 flush_write_cache(fsp, READRAW_FLUSH);
1637 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1638 if(CVAL(inbuf,smb_wct) == 10) {
1640 * This is a large offset (64 bit) read.
1642 #ifdef LARGE_SMB_OFF_T
1644 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1646 #else /* !LARGE_SMB_OFF_T */
1649 * Ensure we haven't been sent a >32 bit offset.
1652 if(IVAL(inbuf,smb_vwv8) != 0) {
1653 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1654 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1655 _smb_setlen(header,0);
1656 if (write_data(smbd_server_fd(),header,4) != 4)
1658 END_PROFILE(SMBreadbraw);
1662 #endif /* LARGE_SMB_OFF_T */
1665 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1666 _smb_setlen(header,0);
1667 if (write_data(smbd_server_fd(),header,4) != 4)
1669 END_PROFILE(SMBreadbraw);
1673 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1674 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1676 /* ensure we don't overrun the packet size */
1677 maxcount = MIN(65535,maxcount);
1679 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1680 SMB_OFF_T size = fsp->size;
1681 SMB_OFF_T sizeneeded = startpos + maxcount;
1683 if (size < sizeneeded) {
1685 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1687 if (!fsp->can_write)
1691 if (startpos >= size)
1694 nread = MIN(maxcount,(size - startpos));
1697 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1698 if (nread < mincount)
1702 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1703 (int)maxcount, (int)mincount, (int)nread ) );
1705 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1707 DEBUG(5,("readbraw finished\n"));
1708 END_PROFILE(SMBreadbraw);
1712 /****************************************************************************
1713 Reply to a lockread (core+ protocol).
1714 ****************************************************************************/
1716 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1724 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1725 BOOL my_lock_ctx = False;
1726 START_PROFILE(SMBlockread);
1728 CHECK_FSP(fsp,conn);
1731 release_level_2_oplocks_on_change(fsp);
1733 numtoread = SVAL(inbuf,smb_vwv1);
1734 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1736 outsize = set_message(outbuf,5,3,True);
1737 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1738 data = smb_buf(outbuf) + 3;
1741 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1742 * protocol request that predates the read/write lock concept.
1743 * Thus instead of asking for a read lock here we need to ask
1744 * for a write lock. JRA.
1745 * Note that the requested lock size is unaffected by max_recv.
1748 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1749 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1751 if (NT_STATUS_V(status)) {
1754 * We used to make lockread a blocking lock. It turns out
1755 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1759 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1761 * A blocking lock was requested. Package up
1762 * this smb into a queued request and push it
1763 * onto the blocking lock queue.
1765 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1766 (SMB_BIG_UINT)numtoread)) {
1767 END_PROFILE(SMBlockread);
1772 END_PROFILE(SMBlockread);
1773 return ERROR_NT(status);
1777 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1780 if (numtoread > max_recv) {
1781 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1782 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1783 (unsigned int)numtoread, (unsigned int)max_recv ));
1784 numtoread = MIN(numtoread,max_recv);
1786 nread = read_file(fsp,data,startpos,numtoread);
1789 END_PROFILE(SMBlockread);
1790 return(UNIXERROR(ERRDOS,ERRnoaccess));
1794 SSVAL(outbuf,smb_vwv0,nread);
1795 SSVAL(outbuf,smb_vwv5,nread+3);
1796 SSVAL(smb_buf(outbuf),1,nread);
1798 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1799 fsp->fnum, (int)numtoread, (int)nread));
1801 END_PROFILE(SMBlockread);
1805 /****************************************************************************
1807 ****************************************************************************/
1809 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1816 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1817 START_PROFILE(SMBread);
1819 CHECK_FSP(fsp,conn);
1822 numtoread = SVAL(inbuf,smb_vwv1);
1823 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1825 outsize = set_message(outbuf,5,3,True);
1826 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1828 * The requested read size cannot be greater than max_recv. JRA.
1830 if (numtoread > max_recv) {
1831 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1832 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1833 (unsigned int)numtoread, (unsigned int)max_recv ));
1834 numtoread = MIN(numtoread,max_recv);
1837 data = smb_buf(outbuf) + 3;
1839 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1840 END_PROFILE(SMBread);
1841 return ERROR_DOS(ERRDOS,ERRlock);
1845 nread = read_file(fsp,data,startpos,numtoread);
1848 END_PROFILE(SMBread);
1849 return(UNIXERROR(ERRDOS,ERRnoaccess));
1853 SSVAL(outbuf,smb_vwv0,nread);
1854 SSVAL(outbuf,smb_vwv5,nread+3);
1855 SCVAL(smb_buf(outbuf),0,1);
1856 SSVAL(smb_buf(outbuf),1,nread);
1858 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1859 fsp->fnum, (int)numtoread, (int)nread ) );
1861 END_PROFILE(SMBread);
1865 /****************************************************************************
1866 Reply to a read and X - possibly using sendfile.
1867 ****************************************************************************/
1869 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1870 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1873 char *data = smb_buf(outbuf);
1875 #if defined(WITH_SENDFILE)
1877 * We can only use sendfile on a non-chained packet and on a file
1878 * that is exclusively oplocked.
1881 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1882 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1883 SMB_STRUCT_STAT sbuf;
1886 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1887 return(UNIXERROR(ERRDOS,ERRnoaccess));
1889 if (startpos > sbuf.st_size)
1892 if (smb_maxcnt > (sbuf.st_size - startpos))
1893 smb_maxcnt = (sbuf.st_size - startpos);
1895 if (smb_maxcnt == 0)
1899 * Set up the packet header before send. We
1900 * assume here the sendfile will work (get the
1901 * correct amount of data).
1904 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1905 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1906 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1907 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1908 SCVAL(outbuf,smb_vwv0,0xFF);
1909 set_message(outbuf,12,smb_maxcnt,False);
1910 header.data = outbuf;
1911 header.length = data - outbuf;
1914 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1916 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1917 * return ENOSYS then pretend we just got a normal read.
1919 if (errno == ENOSYS)
1922 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1923 fsp->fsp_name, strerror(errno) ));
1924 exit_server("send_file_readX sendfile failed");
1927 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1928 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1936 nread = read_file(fsp,data,startpos,smb_maxcnt);
1939 END_PROFILE(SMBreadX);
1940 return(UNIXERROR(ERRDOS,ERRnoaccess));
1943 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1944 SSVAL(outbuf,smb_vwv5,nread);
1945 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1946 SSVAL(smb_buf(outbuf),-2,nread);
1948 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1949 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1954 /****************************************************************************
1955 Reply to a read and X.
1956 ****************************************************************************/
1958 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1960 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1961 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1963 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1965 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1968 START_PROFILE(SMBreadX);
1970 /* If it's an IPC, pass off the pipe handler. */
1972 END_PROFILE(SMBreadX);
1973 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1976 CHECK_FSP(fsp,conn);
1979 set_message(outbuf,12,0,True);
1981 if(CVAL(inbuf,smb_wct) == 12) {
1982 #ifdef LARGE_SMB_OFF_T
1984 * This is a large offset (64 bit) read.
1986 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1988 #else /* !LARGE_SMB_OFF_T */
1991 * Ensure we haven't been sent a >32 bit offset.
1994 if(IVAL(inbuf,smb_vwv10) != 0) {
1995 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1996 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1997 END_PROFILE(SMBreadX);
1998 return ERROR_DOS(ERRDOS,ERRbadaccess);
2001 #endif /* LARGE_SMB_OFF_T */
2005 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2006 END_PROFILE(SMBreadX);
2007 return ERROR_DOS(ERRDOS,ERRlock);
2010 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2012 nread = chain_reply(inbuf,outbuf,length,bufsize);
2014 END_PROFILE(SMBreadX);
2018 /****************************************************************************
2019 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2020 ****************************************************************************/
2022 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2025 ssize_t total_written=0;
2026 size_t numtowrite=0;
2031 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2033 START_PROFILE(SMBwritebraw);
2035 if (srv_is_signing_active()) {
2036 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2039 CHECK_FSP(fsp,conn);
2042 tcount = IVAL(inbuf,smb_vwv1);
2043 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2044 write_through = BITSETW(inbuf+smb_vwv7,0);
2046 /* We have to deal with slightly different formats depending
2047 on whether we are using the core+ or lanman1.0 protocol */
2049 if(Protocol <= PROTOCOL_COREPLUS) {
2050 numtowrite = SVAL(smb_buf(inbuf),-2);
2051 data = smb_buf(inbuf);
2053 numtowrite = SVAL(inbuf,smb_vwv10);
2054 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2057 /* force the error type */
2058 SCVAL(inbuf,smb_com,SMBwritec);
2059 SCVAL(outbuf,smb_com,SMBwritec);
2061 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2062 END_PROFILE(SMBwritebraw);
2063 return(ERROR_DOS(ERRDOS,ERRlock));
2067 nwritten = write_file(fsp,data,startpos,numtowrite);
2069 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2070 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2072 if (nwritten < (ssize_t)numtowrite) {
2073 END_PROFILE(SMBwritebraw);
2074 return(UNIXERROR(ERRHRD,ERRdiskfull));
2077 total_written = nwritten;
2079 /* Return a message to the redirector to tell it to send more bytes */
2080 SCVAL(outbuf,smb_com,SMBwritebraw);
2081 SSVALS(outbuf,smb_vwv0,-1);
2082 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2083 if (!send_smb(smbd_server_fd(),outbuf))
2084 exit_server("reply_writebraw: send_smb failed.");
2086 /* Now read the raw data into the buffer and write it */
2087 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2088 exit_server("secondary writebraw failed");
2091 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2092 numtowrite = smb_len(inbuf);
2094 /* Set up outbuf to return the correct return */
2095 outsize = set_message(outbuf,1,0,True);
2096 SCVAL(outbuf,smb_com,SMBwritec);
2097 SSVAL(outbuf,smb_vwv0,total_written);
2099 if (numtowrite != 0) {
2101 if (numtowrite > BUFFER_SIZE) {
2102 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2103 (unsigned int)numtowrite ));
2104 exit_server("secondary writebraw failed");
2107 if (tcount > nwritten+numtowrite) {
2108 DEBUG(3,("Client overestimated the write %d %d %d\n",
2109 (int)tcount,(int)nwritten,(int)numtowrite));
2112 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2113 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2115 exit_server("secondary writebraw failed");
2118 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2120 if (nwritten < (ssize_t)numtowrite) {
2121 SCVAL(outbuf,smb_rcls,ERRHRD);
2122 SSVAL(outbuf,smb_err,ERRdiskfull);
2126 total_written += nwritten;
2129 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2130 sync_file(conn,fsp);
2132 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2133 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2135 /* we won't return a status if write through is not selected - this follows what WfWg does */
2136 END_PROFILE(SMBwritebraw);
2137 if (!write_through && total_written==tcount) {
2139 #if RABBIT_PELLET_FIX
2141 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2142 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2144 if (!send_keepalive(smbd_server_fd()))
2145 exit_server("reply_writebraw: send of keepalive failed");
2153 /****************************************************************************
2154 Reply to a writeunlock (core+).
2155 ****************************************************************************/
2157 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2158 int size, int dum_buffsize)
2160 ssize_t nwritten = -1;
2164 NTSTATUS status = NT_STATUS_OK;
2165 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2167 START_PROFILE(SMBwriteunlock);
2169 CHECK_FSP(fsp,conn);
2172 numtowrite = SVAL(inbuf,smb_vwv1);
2173 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2174 data = smb_buf(inbuf) + 3;
2176 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2177 WRITE_LOCK,False)) {
2178 END_PROFILE(SMBwriteunlock);
2179 return ERROR_DOS(ERRDOS,ERRlock);
2182 /* The special X/Open SMB protocol handling of
2183 zero length writes is *NOT* done for
2188 nwritten = write_file(fsp,data,startpos,numtowrite);
2190 if (lp_syncalways(SNUM(conn)))
2191 sync_file(conn,fsp);
2193 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2194 END_PROFILE(SMBwriteunlock);
2195 return(UNIXERROR(ERRHRD,ERRdiskfull));
2199 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2200 (SMB_BIG_UINT)startpos);
2201 if (NT_STATUS_V(status)) {
2202 END_PROFILE(SMBwriteunlock);
2203 return ERROR_NT(status);
2207 outsize = set_message(outbuf,1,0,True);
2209 SSVAL(outbuf,smb_vwv0,nwritten);
2211 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2212 fsp->fnum, (int)numtowrite, (int)nwritten));
2214 END_PROFILE(SMBwriteunlock);
2218 /****************************************************************************
2220 ****************************************************************************/
2222 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2225 ssize_t nwritten = -1;
2228 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2230 START_PROFILE(SMBwrite);
2232 /* If it's an IPC, pass off the pipe handler. */
2234 END_PROFILE(SMBwrite);
2235 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2238 CHECK_FSP(fsp,conn);
2241 numtowrite = SVAL(inbuf,smb_vwv1);
2242 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2243 data = smb_buf(inbuf) + 3;
2245 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2246 END_PROFILE(SMBwrite);
2247 return ERROR_DOS(ERRDOS,ERRlock);
2251 * X/Open SMB protocol says that if smb_vwv1 is
2252 * zero then the file size should be extended or
2253 * truncated to the size given in smb_vwv[2-3].
2256 if(numtowrite == 0) {
2258 * This is actually an allocate call, and set EOF. JRA.
2260 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2262 END_PROFILE(SMBwrite);
2263 return ERROR_NT(NT_STATUS_DISK_FULL);
2265 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2267 END_PROFILE(SMBwrite);
2268 return ERROR_NT(NT_STATUS_DISK_FULL);
2271 nwritten = write_file(fsp,data,startpos,numtowrite);
2273 if (lp_syncalways(SNUM(conn)))
2274 sync_file(conn,fsp);
2276 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2277 END_PROFILE(SMBwrite);
2278 return(UNIXERROR(ERRHRD,ERRdiskfull));
2281 outsize = set_message(outbuf,1,0,True);
2283 SSVAL(outbuf,smb_vwv0,nwritten);
2285 if (nwritten < (ssize_t)numtowrite) {
2286 SCVAL(outbuf,smb_rcls,ERRHRD);
2287 SSVAL(outbuf,smb_err,ERRdiskfull);
2290 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2292 END_PROFILE(SMBwrite);
2296 /****************************************************************************
2297 Reply to a write and X.
2298 ****************************************************************************/
2300 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2302 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2303 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2304 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2305 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2306 ssize_t nwritten = -1;
2307 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2308 unsigned int smblen = smb_len(inbuf);
2310 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2311 START_PROFILE(SMBwriteX);
2313 /* If it's an IPC, pass off the pipe handler. */
2315 END_PROFILE(SMBwriteX);
2316 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2319 CHECK_FSP(fsp,conn);
2322 /* Deal with possible LARGE_WRITEX */
2324 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2326 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2327 END_PROFILE(SMBwriteX);
2328 return ERROR_DOS(ERRDOS,ERRbadmem);
2331 data = smb_base(inbuf) + smb_doff;
2333 if(CVAL(inbuf,smb_wct) == 14) {
2334 #ifdef LARGE_SMB_OFF_T
2336 * This is a large offset (64 bit) write.
2338 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2340 #else /* !LARGE_SMB_OFF_T */
2343 * Ensure we haven't been sent a >32 bit offset.
2346 if(IVAL(inbuf,smb_vwv12) != 0) {
2347 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2348 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2349 END_PROFILE(SMBwriteX);
2350 return ERROR_DOS(ERRDOS,ERRbadaccess);
2353 #endif /* LARGE_SMB_OFF_T */
2356 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2357 END_PROFILE(SMBwriteX);
2358 return ERROR_DOS(ERRDOS,ERRlock);
2361 /* X/Open SMB protocol says that, unlike SMBwrite
2362 if the length is zero then NO truncation is
2363 done, just a write of zero. To truncate a file,
2369 nwritten = write_file(fsp,data,startpos,numtowrite);
2371 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2372 END_PROFILE(SMBwriteX);
2373 return(UNIXERROR(ERRHRD,ERRdiskfull));
2376 set_message(outbuf,6,0,True);
2378 SSVAL(outbuf,smb_vwv2,nwritten);
2380 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2382 if (nwritten < (ssize_t)numtowrite) {
2383 SCVAL(outbuf,smb_rcls,ERRHRD);
2384 SSVAL(outbuf,smb_err,ERRdiskfull);
2387 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2388 fsp->fnum, (int)numtowrite, (int)nwritten));
2390 if (lp_syncalways(SNUM(conn)) || write_through)
2391 sync_file(conn,fsp);
2393 END_PROFILE(SMBwriteX);
2394 return chain_reply(inbuf,outbuf,length,bufsize);
2397 /****************************************************************************
2399 ****************************************************************************/
2401 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2407 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2408 START_PROFILE(SMBlseek);
2410 CHECK_FSP(fsp,conn);
2412 flush_write_cache(fsp, SEEK_FLUSH);
2414 mode = SVAL(inbuf,smb_vwv1) & 3;
2415 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2416 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2425 res = fsp->pos + startpos;
2436 if (umode == SEEK_END) {
2437 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2438 if(errno == EINVAL) {
2439 SMB_OFF_T current_pos = startpos;
2440 SMB_STRUCT_STAT sbuf;
2442 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2443 END_PROFILE(SMBlseek);
2444 return(UNIXERROR(ERRDOS,ERRnoaccess));
2447 current_pos += sbuf.st_size;
2449 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2454 END_PROFILE(SMBlseek);
2455 return(UNIXERROR(ERRDOS,ERRnoaccess));
2461 outsize = set_message(outbuf,2,0,True);
2462 SIVAL(outbuf,smb_vwv0,res);
2464 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2465 fsp->fnum, (double)startpos, (double)res, mode));
2467 END_PROFILE(SMBlseek);
2471 /****************************************************************************
2473 ****************************************************************************/
2475 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2477 int outsize = set_message(outbuf,0,0,True);
2478 uint16 fnum = SVAL(inbuf,smb_vwv0);
2479 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2480 START_PROFILE(SMBflush);
2483 CHECK_FSP(fsp,conn);
2486 file_sync_all(conn);
2488 sync_file(conn,fsp);
2491 DEBUG(3,("flush\n"));
2492 END_PROFILE(SMBflush);
2496 /****************************************************************************
2498 ****************************************************************************/
2500 int reply_exit(connection_struct *conn,
2501 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2504 START_PROFILE(SMBexit);
2506 file_close_pid(SVAL(inbuf,smb_pid));
2508 outsize = set_message(outbuf,0,0,True);
2510 DEBUG(3,("exit\n"));
2512 END_PROFILE(SMBexit);
2516 /****************************************************************************
2517 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2518 ****************************************************************************/
2520 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2523 extern struct current_user current_user;
2526 int32 eclass = 0, err = 0;
2527 files_struct *fsp = NULL;
2528 START_PROFILE(SMBclose);
2530 outsize = set_message(outbuf,0,0,True);
2532 /* If it's an IPC, pass off to the pipe handler. */
2534 END_PROFILE(SMBclose);
2535 return reply_pipe_close(conn, inbuf,outbuf);
2538 fsp = file_fsp(inbuf,smb_vwv0);
2541 * We can only use CHECK_FSP if we know it's not a directory.
2544 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2545 END_PROFILE(SMBclose);
2546 return ERROR_DOS(ERRDOS,ERRbadfid);
2549 if(fsp->is_directory) {
2551 * Special case - close NT SMB directory handle.
2553 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2554 close_file(fsp,True);
2557 * Close ordinary file.
2562 /* Save the name for time set in close. */
2563 pstrcpy( file_name, fsp->fsp_name);
2565 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2567 conn->num_files_open));
2570 * close_file() returns the unix errno if an error
2571 * was detected on close - normally this is due to
2572 * a disk full error. If not then it was probably an I/O error.
2575 if((close_err = close_file(fsp,True)) != 0) {
2577 END_PROFILE(SMBclose);
2578 return (UNIXERROR(ERRHRD,ERRgeneral));
2582 * Now take care of any time sent in the close.
2585 mtime = make_unix_date3(inbuf+smb_vwv1);
2587 /* try and set the date */
2588 set_filetime(conn, file_name, mtime);
2592 /* We have a cached error */
2594 END_PROFILE(SMBclose);
2595 return ERROR_DOS(eclass,err);
2598 END_PROFILE(SMBclose);
2602 /****************************************************************************
2603 Reply to a writeclose (Core+ protocol).
2604 ****************************************************************************/
2606 int reply_writeclose(connection_struct *conn,
2607 char *inbuf,char *outbuf, int size, int dum_buffsize)
2610 ssize_t nwritten = -1;
2616 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2617 START_PROFILE(SMBwriteclose);
2619 CHECK_FSP(fsp,conn);
2622 numtowrite = SVAL(inbuf,smb_vwv1);
2623 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2624 mtime = make_unix_date3(inbuf+smb_vwv4);
2625 data = smb_buf(inbuf) + 1;
2627 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2628 END_PROFILE(SMBwriteclose);
2629 return ERROR_DOS(ERRDOS,ERRlock);
2632 nwritten = write_file(fsp,data,startpos,numtowrite);
2634 set_filetime(conn, fsp->fsp_name,mtime);
2637 * More insanity. W2K only closes the file if writelen > 0.
2642 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2644 close_err = close_file(fsp,True);
2647 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2648 fsp->fnum, (int)numtowrite, (int)nwritten,
2649 conn->num_files_open));
2651 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2652 END_PROFILE(SMBwriteclose);
2653 return(UNIXERROR(ERRHRD,ERRdiskfull));
2656 if(close_err != 0) {
2658 END_PROFILE(SMBwriteclose);
2659 return(UNIXERROR(ERRHRD,ERRgeneral));
2662 outsize = set_message(outbuf,1,0,True);
2664 SSVAL(outbuf,smb_vwv0,nwritten);
2665 END_PROFILE(SMBwriteclose);
2669 /****************************************************************************
2671 ****************************************************************************/
2673 int reply_lock(connection_struct *conn,
2674 char *inbuf,char *outbuf, int length, int dum_buffsize)
2676 int outsize = set_message(outbuf,0,0,True);
2677 SMB_BIG_UINT count,offset;
2679 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2680 BOOL my_lock_ctx = False;
2682 START_PROFILE(SMBlock);
2684 CHECK_FSP(fsp,conn);
2686 release_level_2_oplocks_on_change(fsp);
2688 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2689 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2691 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2692 fsp->fd, fsp->fnum, (double)offset, (double)count));
2694 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2695 if (NT_STATUS_V(status)) {
2697 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2698 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2700 * A blocking lock was requested. Package up
2701 * this smb into a queued request and push it
2702 * onto the blocking lock queue.
2704 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2705 END_PROFILE(SMBlock);
2710 END_PROFILE(SMBlock);
2711 return ERROR_NT(status);
2714 END_PROFILE(SMBlock);
2718 /****************************************************************************
2720 ****************************************************************************/
2722 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2725 int outsize = set_message(outbuf,0,0,True);
2726 SMB_BIG_UINT count,offset;
2728 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2729 START_PROFILE(SMBunlock);
2731 CHECK_FSP(fsp,conn);
2733 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2734 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2736 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2737 if (NT_STATUS_V(status)) {
2738 END_PROFILE(SMBunlock);
2739 return ERROR_NT(status);
2742 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2743 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2745 END_PROFILE(SMBunlock);
2749 /****************************************************************************
2751 ****************************************************************************/
2753 int reply_tdis(connection_struct *conn,
2754 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2756 int outsize = set_message(outbuf,0,0,True);
2758 START_PROFILE(SMBtdis);
2760 vuid = SVAL(inbuf,smb_uid);
2763 DEBUG(4,("Invalid connection in tdis\n"));
2764 END_PROFILE(SMBtdis);
2765 return ERROR_DOS(ERRSRV,ERRinvnid);
2770 close_cnum(conn,vuid);
2772 END_PROFILE(SMBtdis);
2776 /****************************************************************************
2778 ****************************************************************************/
2780 int reply_echo(connection_struct *conn,
2781 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2783 int smb_reverb = SVAL(inbuf,smb_vwv0);
2785 unsigned int data_len = smb_buflen(inbuf);
2786 int outsize = set_message(outbuf,1,data_len,True);
2787 START_PROFILE(SMBecho);
2789 if (data_len > BUFFER_SIZE) {
2790 DEBUG(0,("reply_echo: data_len too large.\n"));
2791 END_PROFILE(SMBecho);
2795 /* copy any incoming data back out */
2797 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2799 if (smb_reverb > 100) {
2800 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2804 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2805 SSVAL(outbuf,smb_vwv0,seq_num);
2807 smb_setlen(outbuf,outsize - 4);
2809 if (!send_smb(smbd_server_fd(),outbuf))
2810 exit_server("reply_echo: send_smb failed.");
2813 DEBUG(3,("echo %d times\n", smb_reverb));
2817 END_PROFILE(SMBecho);
2821 /****************************************************************************
2822 Reply to a printopen.
2823 ****************************************************************************/
2825 int reply_printopen(connection_struct *conn,
2826 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2830 START_PROFILE(SMBsplopen);
2832 if (!CAN_PRINT(conn)) {
2833 END_PROFILE(SMBsplopen);
2834 return ERROR_DOS(ERRDOS,ERRnoaccess);
2837 /* Open for exclusive use, write only. */
2838 fsp = print_fsp_open(conn, NULL);
2841 END_PROFILE(SMBsplopen);
2842 return(UNIXERROR(ERRDOS,ERRnoaccess));
2845 outsize = set_message(outbuf,1,0,True);
2846 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2848 DEBUG(3,("openprint fd=%d fnum=%d\n",
2849 fsp->fd, fsp->fnum));
2851 END_PROFILE(SMBsplopen);
2855 /****************************************************************************
2856 Reply to a printclose.
2857 ****************************************************************************/
2859 int reply_printclose(connection_struct *conn,
2860 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2862 int outsize = set_message(outbuf,0,0,True);
2863 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2865 START_PROFILE(SMBsplclose);
2867 CHECK_FSP(fsp,conn);
2869 if (!CAN_PRINT(conn)) {
2870 END_PROFILE(SMBsplclose);
2871 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2874 DEBUG(3,("printclose fd=%d fnum=%d\n",
2875 fsp->fd,fsp->fnum));
2877 close_err = close_file(fsp,True);
2879 if(close_err != 0) {
2881 END_PROFILE(SMBsplclose);
2882 return(UNIXERROR(ERRHRD,ERRgeneral));
2885 END_PROFILE(SMBsplclose);
2889 /****************************************************************************
2890 Reply to a printqueue.
2891 ****************************************************************************/
2893 int reply_printqueue(connection_struct *conn,
2894 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2896 int outsize = set_message(outbuf,2,3,True);
2897 int max_count = SVAL(inbuf,smb_vwv0);
2898 int start_index = SVAL(inbuf,smb_vwv1);
2899 START_PROFILE(SMBsplretq);
2901 /* we used to allow the client to get the cnum wrong, but that
2902 is really quite gross and only worked when there was only
2903 one printer - I think we should now only accept it if they
2904 get it right (tridge) */
2905 if (!CAN_PRINT(conn)) {
2906 END_PROFILE(SMBsplretq);
2907 return ERROR_DOS(ERRDOS,ERRnoaccess);
2910 SSVAL(outbuf,smb_vwv0,0);
2911 SSVAL(outbuf,smb_vwv1,0);
2912 SCVAL(smb_buf(outbuf),0,1);
2913 SSVAL(smb_buf(outbuf),1,0);
2915 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2916 start_index, max_count));
2919 print_queue_struct *queue = NULL;
2920 print_status_struct status;
2921 char *p = smb_buf(outbuf) + 3;
2922 int count = print_queue_status(SNUM(conn), &queue, &status);
2923 int num_to_get = ABS(max_count);
2924 int first = (max_count>0?start_index:start_index+max_count+1);
2930 num_to_get = MIN(num_to_get,count-first);
2933 for (i=first;i<first+num_to_get;i++) {
2934 put_dos_date2(p,0,queue[i].time);
2935 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2936 SSVAL(p,5, queue[i].job);
2937 SIVAL(p,7,queue[i].size);
2939 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2944 outsize = set_message(outbuf,2,28*count+3,False);
2945 SSVAL(outbuf,smb_vwv0,count);
2946 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2947 SCVAL(smb_buf(outbuf),0,1);
2948 SSVAL(smb_buf(outbuf),1,28*count);
2953 DEBUG(3,("%d entries returned in queue\n",count));
2956 END_PROFILE(SMBsplretq);
2960 /****************************************************************************
2961 Reply to a printwrite.
2962 ****************************************************************************/
2964 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2967 int outsize = set_message(outbuf,0,0,True);
2969 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2971 START_PROFILE(SMBsplwr);
2973 if (!CAN_PRINT(conn)) {
2974 END_PROFILE(SMBsplwr);
2975 return ERROR_DOS(ERRDOS,ERRnoaccess);
2978 CHECK_FSP(fsp,conn);
2981 numtowrite = SVAL(smb_buf(inbuf),1);
2982 data = smb_buf(inbuf) + 3;
2984 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2985 END_PROFILE(SMBsplwr);
2986 return(UNIXERROR(ERRHRD,ERRdiskfull));
2989 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2991 END_PROFILE(SMBsplwr);
2995 /****************************************************************************
2996 The guts of the mkdir command, split out so it may be called by the NT SMB
2998 ****************************************************************************/
3000 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3002 BOOL bad_path = False;
3003 SMB_STRUCT_STAT sbuf;
3006 unix_convert(directory,conn,0,&bad_path,&sbuf);
3008 if (ms_has_wild(directory)) {
3009 return NT_STATUS_OBJECT_NAME_INVALID;
3012 if (check_name(directory, conn))
3013 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3016 NTSTATUS nterr = NT_STATUS_OK;
3017 if(errno == ENOENT) {
3018 unix_ERR_class = ERRDOS;
3020 unix_ERR_code = ERRbadpath;
3021 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
3023 unix_ERR_code = ERRbadfile;
3024 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3027 if (!NT_STATUS_IS_OK(nterr))
3029 return map_nt_error_from_unix(errno);
3032 return NT_STATUS_OK;
3035 /****************************************************************************
3037 ****************************************************************************/
3039 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3044 START_PROFILE(SMBmkdir);
3046 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 END_PROFILE(SMBmkdir);
3049 return ERROR_NT(status);
3052 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3054 status = mkdir_internal(conn, directory);
3055 if (!NT_STATUS_IS_OK(status)) {
3056 END_PROFILE(SMBmkdir);
3057 return ERROR_NT(status);
3060 outsize = set_message(outbuf,0,0,True);
3062 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3064 END_PROFILE(SMBmkdir);
3068 /****************************************************************************
3069 Static function used by reply_rmdir to delete an entire directory
3070 tree recursively. Return False on ok, True on fail.
3071 ****************************************************************************/
3073 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3075 const char *dname = NULL;
3077 void *dirptr = OpenDir(conn, directory, False);
3082 while((dname = ReadDirName(dirptr))) {
3086 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3089 /* Construct the full name. */
3090 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3096 pstrcpy(fullname, directory);
3097 pstrcat(fullname, "/");
3098 pstrcat(fullname, dname);
3100 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3105 if(st.st_mode & S_IFDIR) {
3106 if(recursive_rmdir(conn, fullname)!=0) {
3110 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3114 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3123 /****************************************************************************
3124 The internals of the rmdir code - called elsewhere.
3125 ****************************************************************************/
3127 BOOL rmdir_internals(connection_struct *conn, char *directory)
3131 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3132 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3134 * Check to see if the only thing in this directory are
3135 * vetoed files/directories. If so then delete them and
3136 * retry. If we fail to delete any of them (and we *don't*
3137 * do a recursive delete) then fail the rmdir.
3139 BOOL all_veto_files = True;
3141 void *dirptr = OpenDir(conn, directory, False);
3143 if(dirptr != NULL) {
3144 int dirpos = TellDir(dirptr);
3145 while ((dname = ReadDirName(dirptr))) {
3146 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3148 if(!IS_VETO_PATH(conn, dname)) {
3149 all_veto_files = False;
3154 if(all_veto_files) {
3155 SeekDir(dirptr,dirpos);
3156 while ((dname = ReadDirName(dirptr))) {
3160 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3163 /* Construct the full name. */
3164 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3169 pstrcpy(fullname, directory);
3170 pstrcat(fullname, "/");
3171 pstrcat(fullname, dname);
3173 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3175 if(st.st_mode & S_IFDIR) {
3176 if(lp_recursive_veto_delete(SNUM(conn))) {
3177 if(recursive_rmdir(conn, fullname) != 0)
3180 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3182 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3186 /* Retry the rmdir */
3187 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3197 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3202 /****************************************************************************
3204 ****************************************************************************/
3206 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3211 BOOL bad_path = False;
3212 SMB_STRUCT_STAT sbuf;
3214 START_PROFILE(SMBrmdir);
3216 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3217 if (!NT_STATUS_IS_OK(status)) {
3218 END_PROFILE(SMBrmdir);
3219 return ERROR_NT(status);
3222 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3224 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3226 if (check_name(directory,conn)) {
3227 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3228 ok = rmdir_internals(conn, directory);
3232 END_PROFILE(SMBrmdir);
3233 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3236 outsize = set_message(outbuf,0,0,True);
3238 DEBUG( 3, ( "rmdir %s\n", directory ) );
3240 END_PROFILE(SMBrmdir);
3244 /*******************************************************************
3245 Resolve wildcards in a filename rename.
3246 ********************************************************************/
3248 static BOOL resolve_wildcards(const char *name1, char *name2)
3250 fstring root1,root2;
3252 char *p,*p2, *pname1, *pname2;
3253 int available_space;
3256 pname1 = strrchr_m(name1,'/');
3257 pname2 = strrchr_m(name2,'/');
3259 if (!pname1 || !pname2)
3262 fstrcpy(root1,pname1);
3263 fstrcpy(root2,pname2);
3264 p = strrchr_m(root1,'.');
3271 p = strrchr_m(root2,'.');
3305 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3308 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3310 pstrcpy_base(pname2, root2, name2);
3316 /****************************************************************************
3317 Ensure open files have their names updates.
3318 ****************************************************************************/
3320 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3323 BOOL did_rename = False;
3325 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3326 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3327 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3328 fsp->fsp_name, newname ));
3329 string_set(&fsp->fsp_name, newname);
3334 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3335 (unsigned int)dev, (double)inode, newname ));
3338 /****************************************************************************
3339 Rename an open file - given an fsp.
3340 ****************************************************************************/
3342 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3344 SMB_STRUCT_STAT sbuf;
3345 BOOL bad_path = False;
3346 pstring newname_last_component;
3347 NTSTATUS error = NT_STATUS_OK;
3351 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3353 /* Ensure newname contains a '/' */
3354 if(strrchr_m(newname,'/') == 0) {
3357 pstrcpy(tmpstr, "./");
3358 pstrcat(tmpstr, newname);
3359 pstrcpy(newname, tmpstr);
3363 * Check for special case with case preserving and not
3364 * case sensitive. If the old last component differs from the original
3365 * last component only by case, then we should allow
3366 * the rename (user is trying to change the case of the
3370 if((case_sensitive == False) && (case_preserve == True) &&
3371 strequal(newname, fsp->fsp_name)) {
3373 pstring newname_modified_last_component;
3376 * Get the last component of the modified name.
3377 * Note that we guarantee that newname contains a '/'
3380 p = strrchr_m(newname,'/');
3381 pstrcpy(newname_modified_last_component,p+1);
3383 if(strcsequal(newname_modified_last_component,
3384 newname_last_component) == False) {
3386 * Replace the modified last component with
3389 pstrcpy(p+1, newname_last_component);
3394 * If the src and dest names are identical - including case,
3395 * don't do the rename, just return success.
3398 if (strcsequal(fsp->fsp_name, newname)) {
3399 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3401 return NT_STATUS_OK;
3404 dest_exists = vfs_object_exist(conn,newname,NULL);
3406 if(!replace_if_exists && dest_exists) {
3407 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3408 fsp->fsp_name,newname));
3409 return NT_STATUS_OBJECT_NAME_COLLISION;
3412 error = can_rename(newname,conn,&sbuf);
3414 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3415 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3416 nt_errstr(error), fsp->fsp_name,newname));
3417 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3418 error = NT_STATUS_ACCESS_DENIED;
3422 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3423 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3424 fsp->fsp_name,newname));
3425 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3426 return NT_STATUS_OK;
3429 if (errno == ENOTDIR || errno == EISDIR)
3430 error = NT_STATUS_OBJECT_NAME_COLLISION;
3432 error = map_nt_error_from_unix(errno);
3434 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3435 nt_errstr(error), fsp->fsp_name,newname));
3440 /****************************************************************************
3441 The guts of the rename command, split out so it may be called by the NT SMB
3443 ****************************************************************************/
3445 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3449 pstring newname_last_component;
3452 BOOL bad_path1 = False;
3453 BOOL bad_path2 = False;
3455 NTSTATUS error = NT_STATUS_OK;
3457 SMB_STRUCT_STAT sbuf1, sbuf2;
3459 *directory = *mask = 0;
3463 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3464 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3467 * Split the old name into directory and last component
3468 * strings. Note that unix_convert may have stripped off a
3469 * leading ./ from both name and newname if the rename is
3470 * at the root of the share. We need to make sure either both
3471 * name and newname contain a / character or neither of them do
3472 * as this is checked in resolve_wildcards().
3475 p = strrchr_m(name,'/');
3477 pstrcpy(directory,".");
3481 pstrcpy(directory,name);
3483 *p = '/'; /* Replace needed for exceptional test below. */
3487 * We should only check the mangled cache
3488 * here if unix_convert failed. This means
3489 * that the path in 'mask' doesn't exist
3490 * on the file system and so we need to look
3491 * for a possible mangle. This patch from
3492 * Tine Smukavec <valentin.smukavec@hermes.si>.
3495 if (!rc && mangle_is_mangled(mask))
3496 mangle_check_cache( mask );
3498 has_wild = ms_has_wild(mask);
3502 * No wildcards - just process the one file.
3504 BOOL is_short_name = mangle_is_8_3(name, True);
3506 /* Add a terminating '/' to the directory name. */
3507 pstrcat(directory,"/");
3508 pstrcat(directory,mask);
3510 /* Ensure newname contains a '/' also */
3511 if(strrchr_m(newname,'/') == 0) {
3514 pstrcpy(tmpstr, "./");
3515 pstrcat(tmpstr, newname);
3516 pstrcpy(newname, tmpstr);
3519 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3520 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3521 case_sensitive, case_preserve, short_case_preserve, directory,
3522 newname, newname_last_component, is_short_name));
3525 * Check for special case with case preserving and not
3526 * case sensitive, if directory and newname are identical,
3527 * and the old last component differs from the original
3528 * last component only by case, then we should allow
3529 * the rename (user is trying to change the case of the
3532 if((case_sensitive == False) &&
3533 (((case_preserve == True) &&
3534 (is_short_name == False)) ||
3535 ((short_case_preserve == True) &&
3536 (is_short_name == True))) &&
3537 strcsequal(directory, newname)) {
3538 pstring newname_modified_last_component;
3541 * Get the last component of the modified name.
3542 * Note that we guarantee that newname contains a '/'
3545 p = strrchr_m(newname,'/');
3546 pstrcpy(newname_modified_last_component,p+1);
3548 if(strcsequal(newname_modified_last_component,
3549 newname_last_component) == False) {
3551 * Replace the modified last component with
3554 pstrcpy(p+1, newname_last_component);
3558 resolve_wildcards(directory,newname);
3561 * The source object must exist.
3564 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3565 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3566 directory,newname));
3568 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3570 * Must return different errors depending on whether the parent
3571 * directory existed or not.
3574 p = strrchr_m(directory, '/');
3576 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3578 if (vfs_object_exist(conn, directory, NULL))
3579 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3580 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3582 error = map_nt_error_from_unix(errno);
3583 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3584 nt_errstr(error), directory,newname));
3589 error = can_rename(directory,conn,&sbuf1);
3591 if (!NT_STATUS_IS_OK(error)) {
3592 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3593 nt_errstr(error), directory,newname));
3598 * If the src and dest names are identical - including case,
3599 * don't do the rename, just return success.
3602 if (strcsequal(directory, newname)) {
3603 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3604 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3605 return NT_STATUS_OK;
3608 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3609 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3610 directory,newname));
3611 return NT_STATUS_OBJECT_NAME_COLLISION;
3614 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3615 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3616 directory,newname));
3617 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3618 return NT_STATUS_OK;
3621 if (errno == ENOTDIR || errno == EISDIR)
3622 error = NT_STATUS_OBJECT_NAME_COLLISION;
3624 error = map_nt_error_from_unix(errno);
3626 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3627 nt_errstr(error), directory,newname));
3632 * Wildcards - process each file that matches.
3634 void *dirptr = NULL;
3638 if (check_name(directory,conn))
3639 dirptr = OpenDir(conn, directory, True);
3642 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3644 if (strequal(mask,"????????.???"))
3647 while ((dname = ReadDirName(dirptr))) {
3650 pstrcpy(fname,dname);
3652 if(!mask_match(fname, mask, case_sensitive))
3655 error = NT_STATUS_ACCESS_DENIED;
3656 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3657 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3658 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3659 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3662 error = can_rename(fname,conn,&sbuf1);
3663 if (!NT_STATUS_IS_OK(error)) {
3664 DEBUG(6,("rename %s refused\n", fname));
3667 pstrcpy(destname,newname);
3669 if (!resolve_wildcards(fname,destname)) {
3670 DEBUG(6,("resolve_wildcards %s %s failed\n",
3675 if (!replace_if_exists &&
3676 vfs_file_exist(conn,destname, NULL)) {
3677 DEBUG(6,("file_exist %s\n", destname));
3678 error = NT_STATUS_OBJECT_NAME_COLLISION;
3682 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3683 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3686 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3692 if (count == 0 && NT_STATUS_IS_OK(error)) {
3693 error = map_nt_error_from_unix(errno);
3699 /****************************************************************************
3701 ****************************************************************************/
3703 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3712 START_PROFILE(SMBmv);
3714 p = smb_buf(inbuf) + 1;
3715 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3716 if (!NT_STATUS_IS_OK(status)) {
3718 return ERROR_NT(status);
3721 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3722 if (!NT_STATUS_IS_OK(status)) {
3724 return ERROR_NT(status);
3727 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3728 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3730 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3732 status = rename_internals(conn, name, newname, False);
3733 if (!NT_STATUS_IS_OK(status)) {
3735 return ERROR_NT(status);
3739 * Win2k needs a changenotify request response before it will
3740 * update after a rename..
3742 process_pending_change_notify_queue((time_t)0);
3743 outsize = set_message(outbuf,0,0,True);
3749 /*******************************************************************
3750 Copy a file as part of a reply_copy.
3751 ******************************************************************/
3753 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3754 int count,BOOL target_is_directory, int *err_ret)
3757 SMB_STRUCT_STAT src_sbuf, sbuf2;
3759 files_struct *fsp1,*fsp2;
3764 pstrcpy(dest,dest1);
3765 if (target_is_directory) {
3766 char *p = strrchr_m(src,'/');
3775 if (!vfs_file_exist(conn,src,&src_sbuf))
3778 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3779 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3784 if (!target_is_directory && count)
3785 ofun = FILE_EXISTS_OPEN;
3787 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3788 ZERO_STRUCTP(&sbuf2);
3790 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3791 ofun,src_sbuf.st_mode,0,&Access,&action);
3794 close_file(fsp1,False);
3798 if ((ofun&3) == 1) {
3799 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3800 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3802 * Stop the copy from occurring.
3805 src_sbuf.st_size = 0;
3809 if (src_sbuf.st_size)
3810 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3812 close_file(fsp1,False);
3814 /* Ensure the modtime is set correctly on the destination file. */
3815 fsp2->pending_modtime = src_sbuf.st_mtime;
3818 * As we are opening fsp1 read-only we only expect
3819 * an error on close on fsp2 if we are out of space.
3820 * Thus we don't look at the error return from the
3823 *err_ret = close_file(fsp2,False);
3825 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3828 /****************************************************************************
3829 Reply to a file copy.
3830 ****************************************************************************/
3832 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3837 pstring mask,newname;
3840 int error = ERRnoaccess;
3844 int tid2 = SVAL(inbuf,smb_vwv0);
3845 int ofun = SVAL(inbuf,smb_vwv1);
3846 int flags = SVAL(inbuf,smb_vwv2);
3847 BOOL target_is_directory=False;
3848 BOOL bad_path1 = False;
3849 BOOL bad_path2 = False;
3851 SMB_STRUCT_STAT sbuf1, sbuf2;
3854 START_PROFILE(SMBcopy);
3856 *directory = *mask = 0;
3859 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 END_PROFILE(SMBcopy);
3862 return ERROR_NT(status);
3864 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3865 if (!NT_STATUS_IS_OK(status)) {
3866 END_PROFILE(SMBcopy);
3867 return ERROR_NT(status);
3870 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3872 if (tid2 != conn->cnum) {
3873 /* can't currently handle inter share copies XXXX */
3874 DEBUG(3,("Rejecting inter-share copy\n"));
3875 END_PROFILE(SMBcopy);
3876 return ERROR_DOS(ERRSRV,ERRinvdevice);
3879 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3880 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3882 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3883 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3885 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3887 if ((flags&1) && target_is_directory) {
3888 END_PROFILE(SMBcopy);
3889 return ERROR_DOS(ERRDOS,ERRbadfile);
3892 if ((flags&2) && !target_is_directory) {
3893 END_PROFILE(SMBcopy);
3894 return ERROR_DOS(ERRDOS,ERRbadpath);
3897 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3898 /* wants a tree copy! XXXX */
3899 DEBUG(3,("Rejecting tree copy\n"));
3900 END_PROFILE(SMBcopy);
3901 return ERROR_DOS(ERRSRV,ERRerror);
3904 p = strrchr_m(name,'/');
3906 pstrcpy(directory,"./");
3910 pstrcpy(directory,name);
3915 * We should only check the mangled cache
3916 * here if unix_convert failed. This means
3917 * that the path in 'mask' doesn't exist
3918 * on the file system and so we need to look
3919 * for a possible mangle. This patch from
3920 * Tine Smukavec <valentin.smukavec@hermes.si>.
3923 if (!rc && mangle_is_mangled(mask))
3924 mangle_check_cache( mask );
3926 has_wild = ms_has_wild(mask);
3929 pstrcat(directory,"/");
3930 pstrcat(directory,mask);
3931 if (resolve_wildcards(directory,newname) &&
3932 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3936 END_PROFILE(SMBcopy);
3937 return(UNIXERROR(ERRHRD,ERRgeneral));
3940 exists = vfs_file_exist(conn,directory,NULL);
3943 void *dirptr = NULL;
3947 if (check_name(directory,conn))
3948 dirptr = OpenDir(conn, directory, True);
3953 if (strequal(mask,"????????.???"))
3956 while ((dname = ReadDirName(dirptr))) {
3958 pstrcpy(fname,dname);
3960 if(!mask_match(fname, mask, case_sensitive))
3963 error = ERRnoaccess;
3964 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3965 pstrcpy(destname,newname);
3966 if (resolve_wildcards(fname,destname) &&
3967 copy_file(fname,destname,conn,ofun,
3968 count,target_is_directory,&err))
3970 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3978 /* Error on close... */
3980 END_PROFILE(SMBcopy);
3981 return(UNIXERROR(ERRHRD,ERRgeneral));
3985 END_PROFILE(SMBcopy);
3986 return ERROR_DOS(ERRDOS,error);
3988 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3989 unix_ERR_class = ERRDOS;
3990 unix_ERR_code = ERRbadpath;
3992 END_PROFILE(SMBcopy);
3993 return(UNIXERROR(ERRDOS,error));
3997 outsize = set_message(outbuf,1,0,True);
3998 SSVAL(outbuf,smb_vwv0,count);
4000 END_PROFILE(SMBcopy);
4004 /****************************************************************************
4006 ****************************************************************************/
4008 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4016 START_PROFILE(pathworks_setdir);
4019 if (!CAN_SETDIR(snum)) {
4020 END_PROFILE(pathworks_setdir);
4021 return ERROR_DOS(ERRDOS,ERRnoaccess);
4024 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4025 if (!NT_STATUS_IS_OK(status)) {
4026 END_PROFILE(pathworks_setdir);
4027 return ERROR_NT(status);
4030 if (strlen(newdir) == 0) {
4033 ok = vfs_directory_exist(conn,newdir,NULL);
4035 string_set(&conn->connectpath,newdir);
4039 END_PROFILE(pathworks_setdir);
4040 return ERROR_DOS(ERRDOS,ERRbadpath);
4043 outsize = set_message(outbuf,0,0,True);
4044 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4046 DEBUG(3,("setdir %s\n", newdir));
4048 END_PROFILE(pathworks_setdir);
4052 /****************************************************************************
4053 Get a lock pid, dealing with large count requests.
4054 ****************************************************************************/
4056 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4058 if(!large_file_format)
4059 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4061 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4064 /****************************************************************************
4065 Get a lock count, dealing with large count requests.
4066 ****************************************************************************/
4068 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4070 SMB_BIG_UINT count = 0;
4072 if(!large_file_format) {
4073 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4076 #if defined(HAVE_LONGLONG)
4077 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4078 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4079 #else /* HAVE_LONGLONG */
4082 * NT4.x seems to be broken in that it sends large file (64 bit)
4083 * lockingX calls even if the CAP_LARGE_FILES was *not*
4084 * negotiated. For boxes without large unsigned ints truncate the
4085 * lock count by dropping the top 32 bits.
4088 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4089 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4090 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4091 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4092 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4095 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4096 #endif /* HAVE_LONGLONG */
4102 #if !defined(HAVE_LONGLONG)
4103 /****************************************************************************
4104 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4105 ****************************************************************************/
4107 static uint32 map_lock_offset(uint32 high, uint32 low)
4111 uint32 highcopy = high;
4114 * Try and find out how many significant bits there are in high.
4117 for(i = 0; highcopy; i++)
4121 * We use 31 bits not 32 here as POSIX
4122 * lock offsets may not be negative.
4125 mask = (~0) << (31 - i);
4128 return 0; /* Fail. */
4134 #endif /* !defined(HAVE_LONGLONG) */
4136 /****************************************************************************
4137 Get a lock offset, dealing with large offset requests.
4138 ****************************************************************************/
4140 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4142 SMB_BIG_UINT offset = 0;
4146 if(!large_file_format) {
4147 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4150 #if defined(HAVE_LONGLONG)
4151 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4152 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4153 #else /* HAVE_LONGLONG */
4156 * NT4.x seems to be broken in that it sends large file (64 bit)
4157 * lockingX calls even if the CAP_LARGE_FILES was *not*
4158 * negotiated. For boxes without large unsigned ints mangle the
4159 * lock offset by mapping the top 32 bits onto the lower 32.
4162 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4163 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4164 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4167 if((new_low = map_lock_offset(high, low)) == 0) {
4169 return (SMB_BIG_UINT)-1;
4172 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4173 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4174 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4175 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4178 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4179 #endif /* HAVE_LONGLONG */
4185 /****************************************************************************
4186 Reply to a lockingX request.
4187 ****************************************************************************/
4189 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4191 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4192 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4193 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4194 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4195 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4196 SMB_BIG_UINT count = 0, offset = 0;
4198 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4201 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4203 BOOL my_lock_ctx = False;
4206 START_PROFILE(SMBlockingX);
4208 CHECK_FSP(fsp,conn);
4210 data = smb_buf(inbuf);
4212 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4213 /* we don't support these - and CANCEL_LOCK makes w2k
4214 and XP reboot so I don't really want to be
4215 compatible! (tridge) */
4216 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4219 /* Check if this is an oplock break on a file
4220 we have granted an oplock on.
4222 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4223 /* Client can insist on breaking to none. */
4224 BOOL break_to_none = (oplocklevel == 0);
4226 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4227 (unsigned int)oplocklevel, fsp->fnum ));
4230 * Make sure we have granted an exclusive or batch oplock on this file.
4233 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4234 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4235 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4237 /* if this is a pure oplock break request then don't send a reply */
4238 if (num_locks == 0 && num_ulocks == 0) {
4239 END_PROFILE(SMBlockingX);
4242 END_PROFILE(SMBlockingX);
4243 return ERROR_DOS(ERRDOS,ERRlock);
4247 if (remove_oplock(fsp, break_to_none) == False) {
4248 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4252 /* if this is a pure oplock break request then don't send a reply */
4253 if (num_locks == 0 && num_ulocks == 0) {
4254 /* Sanity check - ensure a pure oplock break is not a
4256 if(CVAL(inbuf,smb_vwv0) != 0xff)
4257 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4258 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4259 END_PROFILE(SMBlockingX);
4265 * We do this check *after* we have checked this is not a oplock break
4266 * response message. JRA.
4269 release_level_2_oplocks_on_change(fsp);
4271 /* Data now points at the beginning of the list
4272 of smb_unlkrng structs */
4273 for(i = 0; i < (int)num_ulocks; i++) {
4274 lock_pid = get_lock_pid( data, i, large_file_format);
4275 count = get_lock_count( data, i, large_file_format);
4276 offset = get_lock_offset( data, i, large_file_format, &err);
4279 * There is no error code marked "stupid client bug".... :-).
4282 END_PROFILE(SMBlockingX);
4283 return ERROR_DOS(ERRDOS,ERRnoaccess);
4286 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4287 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4289 status = do_unlock(fsp,conn,lock_pid,count,offset);
4290 if (NT_STATUS_V(status)) {
4291 END_PROFILE(SMBlockingX);
4292 return ERROR_NT(status);
4296 /* Setup the timeout in seconds. */
4298 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4300 /* Now do any requested locks */
4301 data += ((large_file_format ? 20 : 10)*num_ulocks);
4303 /* Data now points at the beginning of the list
4304 of smb_lkrng structs */
4306 for(i = 0; i < (int)num_locks; i++) {
4307 lock_pid = get_lock_pid( data, i, large_file_format);
4308 count = get_lock_count( data, i, large_file_format);
4309 offset = get_lock_offset( data, i, large_file_format, &err);
4312 * There is no error code marked "stupid client bug".... :-).
4315 END_PROFILE(SMBlockingX);
4316 return ERROR_DOS(ERRDOS,ERRnoaccess);
4319 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4320 (double)offset, (double)count, (unsigned int)lock_pid,
4321 fsp->fsp_name, (int)lock_timeout ));
4323 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4324 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4325 if (NT_STATUS_V(status)) {
4326 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4328 * A blocking lock was requested. Package up
4329 * this smb into a queued request and push it
4330 * onto the blocking lock queue.
4332 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4333 END_PROFILE(SMBlockingX);
4341 /* If any of the above locks failed, then we must unlock
4342 all of the previous locks (X/Open spec). */
4343 if (i != num_locks && num_locks != 0) {
4345 * Ensure we don't do a remove on the lock that just failed,
4346 * as under POSIX rules, if we have a lock already there, we
4347 * will delete it (and we shouldn't) .....
4349 for(i--; i >= 0; i--) {
4350 lock_pid = get_lock_pid( data, i, large_file_format);
4351 count = get_lock_count( data, i, large_file_format);
4352 offset = get_lock_offset( data, i, large_file_format, &err);
4355 * There is no error code marked "stupid client bug".... :-).
4358 END_PROFILE(SMBlockingX);
4359 return ERROR_DOS(ERRDOS,ERRnoaccess);
4362 do_unlock(fsp,conn,lock_pid,count,offset);
4364 END_PROFILE(SMBlockingX);
4365 return ERROR_NT(status);
4368 set_message(outbuf,2,0,True);
4370 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4371 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4373 END_PROFILE(SMBlockingX);
4374 return chain_reply(inbuf,outbuf,length,bufsize);
4377 /****************************************************************************
4378 Reply to a SMBreadbmpx (read block multiplex) request.
4379 ****************************************************************************/
4381 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4392 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4393 START_PROFILE(SMBreadBmpx);
4395 /* this function doesn't seem to work - disable by default */
4396 if (!lp_readbmpx()) {
4397 END_PROFILE(SMBreadBmpx);
4398 return ERROR_DOS(ERRSRV,ERRuseSTD);
4401 outsize = set_message(outbuf,8,0,True);
4403 CHECK_FSP(fsp,conn);
4406 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4407 maxcount = SVAL(inbuf,smb_vwv3);
4409 data = smb_buf(outbuf);
4410 pad = ((long)data)%4;
4415 max_per_packet = bufsize-(outsize+pad);
4419 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4420 END_PROFILE(SMBreadBmpx);
4421 return ERROR_DOS(ERRDOS,ERRlock);
4425 size_t N = MIN(max_per_packet,tcount-total_read);
4427 nread = read_file(fsp,data,startpos,N);
4432 if (nread < (ssize_t)N)
4433 tcount = total_read + nread;
4435 set_message(outbuf,8,nread,False);
4436 SIVAL(outbuf,smb_vwv0,startpos);
4437 SSVAL(outbuf,smb_vwv2,tcount);
4438 SSVAL(outbuf,smb_vwv6,nread);
4439 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4441 if (!send_smb(smbd_server_fd(),outbuf))
4442 exit_server("reply_readbmpx: send_smb failed.");
4444 total_read += nread;
4446 } while (total_read < (ssize_t)tcount);
4448 END_PROFILE(SMBreadBmpx);
4452 /****************************************************************************
4453 Reply to a SMBsetattrE.
4454 ****************************************************************************/
4456 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4458 struct utimbuf unix_times;
4460 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4461 START_PROFILE(SMBsetattrE);
4463 outsize = set_message(outbuf,0,0,True);
4465 if(!fsp || (fsp->conn != conn)) {
4466 END_PROFILE(SMBgetattrE);
4467 return ERROR_DOS(ERRDOS,ERRbadfid);
4471 * Convert the DOS times into unix times. Ignore create
4472 * time as UNIX can't set this.
4475 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4476 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4479 * Patch from Ray Frush <frush@engr.colostate.edu>
4480 * Sometimes times are sent as zero - ignore them.
4483 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4484 /* Ignore request */
4485 if( DEBUGLVL( 3 ) ) {
4486 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4487 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4489 END_PROFILE(SMBsetattrE);
4491 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4492 /* set modify time = to access time if modify time was 0 */
4493 unix_times.modtime = unix_times.actime;
4496 /* Set the date on this file */
4497 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4498 END_PROFILE(SMBsetattrE);
4499 return ERROR_DOS(ERRDOS,ERRnoaccess);
4502 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4503 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4505 END_PROFILE(SMBsetattrE);
4510 /* Back from the dead for OS/2..... JRA. */
4512 /****************************************************************************
4513 Reply to a SMBwritebmpx (write block multiplex primary) request.
4514 ****************************************************************************/
4516 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4519 ssize_t nwritten = -1;
4526 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4527 START_PROFILE(SMBwriteBmpx);
4529 CHECK_FSP(fsp,conn);
4533 tcount = SVAL(inbuf,smb_vwv1);
4534 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4535 write_through = BITSETW(inbuf+smb_vwv7,0);
4536 numtowrite = SVAL(inbuf,smb_vwv10);
4537 smb_doff = SVAL(inbuf,smb_vwv11);
4539 data = smb_base(inbuf) + smb_doff;
4541 /* If this fails we need to send an SMBwriteC response,
4542 not an SMBwritebmpx - set this up now so we don't forget */
4543 SCVAL(outbuf,smb_com,SMBwritec);
4545 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4546 END_PROFILE(SMBwriteBmpx);
4547 return(ERROR_DOS(ERRDOS,ERRlock));
4550 nwritten = write_file(fsp,data,startpos,numtowrite);
4552 if(lp_syncalways(SNUM(conn)) || write_through)
4553 sync_file(conn,fsp);
4555 if(nwritten < (ssize_t)numtowrite) {
4556 END_PROFILE(SMBwriteBmpx);
4557 return(UNIXERROR(ERRHRD,ERRdiskfull));
4560 /* If the maximum to be written to this file
4561 is greater than what we just wrote then set
4562 up a secondary struct to be attached to this
4563 fd, we will use this to cache error messages etc. */
4565 if((ssize_t)tcount > nwritten) {
4566 write_bmpx_struct *wbms;
4567 if(fsp->wbmpx_ptr != NULL)
4568 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4570 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4572 DEBUG(0,("Out of memory in reply_readmpx\n"));
4573 END_PROFILE(SMBwriteBmpx);
4574 return(ERROR_DOS(ERRSRV,ERRnoresource));
4576 wbms->wr_mode = write_through;
4577 wbms->wr_discard = False; /* No errors yet */
4578 wbms->wr_total_written = nwritten;
4579 wbms->wr_errclass = 0;
4581 fsp->wbmpx_ptr = wbms;
4584 /* We are returning successfully, set the message type back to
4586 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4588 outsize = set_message(outbuf,1,0,True);
4590 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4592 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4593 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4595 if (write_through && tcount==nwritten) {
4596 /* We need to send both a primary and a secondary response */
4597 smb_setlen(outbuf,outsize - 4);
4598 if (!send_smb(smbd_server_fd(),outbuf))
4599 exit_server("reply_writebmpx: send_smb failed.");
4601 /* Now the secondary */
4602 outsize = set_message(outbuf,1,0,True);
4603 SCVAL(outbuf,smb_com,SMBwritec);
4604 SSVAL(outbuf,smb_vwv0,nwritten);
4607 END_PROFILE(SMBwriteBmpx);
4611 /****************************************************************************
4612 Reply to a SMBwritebs (write block multiplex secondary) request.
4613 ****************************************************************************/
4615 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4618 ssize_t nwritten = -1;
4625 write_bmpx_struct *wbms;
4626 BOOL send_response = False;
4627 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4628 START_PROFILE(SMBwriteBs);
4630 CHECK_FSP(fsp,conn);
4633 tcount = SVAL(inbuf,smb_vwv1);
4634 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4635 numtowrite = SVAL(inbuf,smb_vwv6);
4636 smb_doff = SVAL(inbuf,smb_vwv7);
4638 data = smb_base(inbuf) + smb_doff;
4640 /* We need to send an SMBwriteC response, not an SMBwritebs */
4641 SCVAL(outbuf,smb_com,SMBwritec);
4643 /* This fd should have an auxiliary struct attached,
4644 check that it does */
4645 wbms = fsp->wbmpx_ptr;
4647 END_PROFILE(SMBwriteBs);
4651 /* If write through is set we can return errors, else we must cache them */
4652 write_through = wbms->wr_mode;
4654 /* Check for an earlier error */
4655 if(wbms->wr_discard) {
4656 END_PROFILE(SMBwriteBs);
4657 return -1; /* Just discard the packet */
4660 nwritten = write_file(fsp,data,startpos,numtowrite);
4662 if(lp_syncalways(SNUM(conn)) || write_through)
4663 sync_file(conn,fsp);
4665 if (nwritten < (ssize_t)numtowrite) {
4667 /* We are returning an error - we can delete the aux struct */
4670 fsp->wbmpx_ptr = NULL;
4671 END_PROFILE(SMBwriteBs);
4672 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4674 END_PROFILE(SMBwriteBs);
4675 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4678 /* Increment the total written, if this matches tcount
4679 we can discard the auxiliary struct (hurrah !) and return a writeC */
4680 wbms->wr_total_written += nwritten;
4681 if(wbms->wr_total_written >= tcount) {
4682 if (write_through) {
4683 outsize = set_message(outbuf,1,0,True);
4684 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4685 send_response = True;
4689 fsp->wbmpx_ptr = NULL;
4693 END_PROFILE(SMBwriteBs);
4697 END_PROFILE(SMBwriteBs);
4701 /****************************************************************************
4702 Reply to a SMBgetattrE.
4703 ****************************************************************************/
4705 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4707 SMB_STRUCT_STAT sbuf;
4710 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4711 START_PROFILE(SMBgetattrE);
4713 outsize = set_message(outbuf,11,0,True);
4715 if(!fsp || (fsp->conn != conn)) {
4716 END_PROFILE(SMBgetattrE);
4717 return ERROR_DOS(ERRDOS,ERRbadfid);
4720 /* Do an fstat on this file */
4721 if(fsp_stat(fsp, &sbuf)) {
4722 END_PROFILE(SMBgetattrE);
4723 return(UNIXERROR(ERRDOS,ERRnoaccess));
4726 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4729 * Convert the times into dos times. Set create
4730 * date to be last modify date as UNIX doesn't save
4734 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4735 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4736 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4739 SIVAL(outbuf,smb_vwv6,0);
4740 SIVAL(outbuf,smb_vwv8,0);
4742 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4743 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4744 SIVAL(outbuf,smb_vwv8,allocation_size);
4746 SSVAL(outbuf,smb_vwv10, mode);
4748 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4750 END_PROFILE(SMBgetattrE);