- removed smb.conf.5.html as it now comes as part of htmldocs
[Samba/gbeck.git] / source / smbd / reply.c
blob1abb084124b030153bc06c08f5c378b1dd2b958d
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
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
27 #include "includes.h"
28 #include "trans2.h"
29 #include "nterr.h"
31 /* look in server.c for some explanation of these variables */
32 extern int Protocol;
33 extern int DEBUGLEVEL;
34 extern int max_send;
35 extern int max_recv;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern fstring global_myworkgroup;
42 extern int Client;
43 extern int global_oplock_break;
44 uint32 global_client_caps = 0;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
50 static void overflow_attack(int len)
52 if( DEBUGLVL( 0 ) )
54 dbgtext( "ERROR: Invalid password length %d.\n", len );
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
59 exit_server("possible attack");
63 /****************************************************************************
64 reply to an special message
65 ****************************************************************************/
66 int reply_special(char *inbuf,char *outbuf)
68 int outsize = 4;
69 int msg_type = CVAL(inbuf,0);
70 int msg_flags = CVAL(inbuf,1);
71 pstring name1,name2;
72 extern fstring remote_machine;
73 extern fstring local_machine;
74 int len;
75 char name_type = 0;
77 *name1 = *name2 = 0;
79 bzero(outbuf,smb_size);
81 smb_setlen(outbuf,0);
83 switch (msg_type) {
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
86 CVAL(outbuf,3) = 0;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
90 return(0);
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 name1,name2));
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
102 fstrcpy(local_machine,name1);
103 len = strlen(local_machine);
104 if (len == 16) {
105 name_type = local_machine[15];
106 local_machine[15] = 0;
108 trim_string(local_machine," "," ");
109 strlower(local_machine);
111 if (name_type == 'R') {
112 /* We are being asked for a pathworks session ---
113 no thanks! */
114 CVAL(outbuf, 0) = 0x83;
115 break;
118 add_session_user(remote_machine);
120 reload_services(True);
121 reopen_logs();
123 if (lp_status(-1)) {
124 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
127 break;
129 case 0x89: /* session keepalive request
130 (some old clients produce this?) */
131 CVAL(outbuf,0) = 0x85;
132 CVAL(outbuf,3) = 0;
133 break;
135 case 0x82: /* positive session response */
136 case 0x83: /* negative session response */
137 case 0x84: /* retarget session response */
138 DEBUG(0,("Unexpected session response\n"));
139 break;
141 case 0x85: /* session keepalive */
142 default:
143 return(0);
146 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
147 msg_type, msg_flags));
149 return(outsize);
153 /*******************************************************************
154 work out what error to give to a failed connection
155 ********************************************************************/
156 static int connection_error(char *inbuf,char *outbuf,int ecode)
158 if (ecode == ERRnoipc) {
159 return(ERROR(ERRDOS,ERRnoipc));
162 return(ERROR(ERRSRV,ecode));
167 /****************************************************************************
168 parse a share descriptor string
169 ****************************************************************************/
170 static void parse_connect(char *p,char *service,char *user,
171 char *password,int *pwlen,char *dev)
173 char *p2;
175 DEBUG(4,("parsing connect string %s\n",p));
177 p2 = strrchr(p,'\\');
178 if (p2 == NULL)
179 fstrcpy(service,p);
180 else
181 fstrcpy(service,p2+1);
183 p += strlen(p) + 2;
185 fstrcpy(password,p);
186 *pwlen = strlen(password);
188 p += strlen(p) + 2;
190 fstrcpy(dev,p);
192 *user = 0;
193 p = strchr(service,'%');
194 if (p != NULL)
196 *p = 0;
197 fstrcpy(user,p+1);
204 /****************************************************************************
205 reply to a tcon
206 ****************************************************************************/
207 int reply_tcon(connection_struct *conn,
208 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
210 pstring service;
211 pstring user;
212 pstring password;
213 pstring dev;
214 int outsize = 0;
215 uint16 vuid = SVAL(inbuf,smb_uid);
216 int pwlen=0;
217 int ecode = -1;
219 *service = *user = *password = *dev = 0;
221 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
224 * Pass the user through the NT -> unix user mapping
225 * function.
228 (void)map_username(user);
231 * Do any UNIX username case mangling.
233 (void)Get_Pwnam( user, True);
235 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
237 if (!conn) {
238 return(connection_error(inbuf,outbuf,ecode));
241 outsize = set_message(outbuf,2,0,True);
242 SSVAL(outbuf,smb_vwv0,max_recv);
243 SSVAL(outbuf,smb_vwv1,conn->cnum);
244 SSVAL(outbuf,smb_tid,conn->cnum);
246 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
247 service, user, conn->cnum));
249 return(outsize);
253 /****************************************************************************
254 reply to a tcon and X
255 ****************************************************************************/
256 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
258 pstring service;
259 pstring user;
260 pstring password;
261 pstring devicename;
262 int ecode = -1;
263 uint16 vuid = SVAL(inbuf,smb_uid);
264 int passlen = SVAL(inbuf,smb_vwv3);
265 char *path;
266 char *p;
268 *service = *user = *password = *devicename = 0;
270 /* we might have to close an old one */
271 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
272 close_cnum(conn,vuid);
275 if (passlen > MAX_PASS_LEN) {
276 overflow_attack(passlen);
279 memcpy(password,smb_buf(inbuf),passlen);
280 password[passlen]=0;
281 path = smb_buf(inbuf) + passlen;
283 if (passlen != 24) {
284 if (strequal(password," "))
285 *password = 0;
286 passlen = strlen(password);
289 fstrcpy(service,path+2);
290 p = strchr(service,'\\');
291 if (!p)
292 return(ERROR(ERRSRV,ERRinvnetname));
293 *p = 0;
294 fstrcpy(service,p+1);
295 p = strchr(service,'%');
296 if (p) {
297 *p++ = 0;
298 fstrcpy(user,p);
300 StrnCpy(devicename,path + strlen(path) + 1,6);
301 DEBUG(4,("Got device type %s\n",devicename));
304 * Pass the user through the NT -> unix user mapping
305 * function.
308 (void)map_username(user);
311 * Do any UNIX username case mangling.
313 (void)Get_Pwnam(user, True);
315 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
317 if (!conn)
318 return(connection_error(inbuf,outbuf,ecode));
320 if (Protocol < PROTOCOL_NT1) {
321 set_message(outbuf,2,strlen(devicename)+1,True);
322 pstrcpy(smb_buf(outbuf),devicename);
323 } else {
324 char *fsname = lp_fstype(SNUM(conn));
326 set_message(outbuf,3,3,True);
328 p = smb_buf(outbuf);
329 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
330 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
332 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
334 /* what does setting this bit do? It is set by NT4 and
335 may affect the ability to autorun mounted cdroms */
336 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
339 DEBUG(3,("tconX service=%s user=%s\n",
340 service, user));
342 /* set the incoming and outgoing tid to the just created one */
343 SSVAL(inbuf,smb_tid,conn->cnum);
344 SSVAL(outbuf,smb_tid,conn->cnum);
346 return chain_reply(inbuf,outbuf,length,bufsize);
350 /****************************************************************************
351 reply to an unknown type
352 ****************************************************************************/
353 int reply_unknown(char *inbuf,char *outbuf)
355 int type;
356 type = CVAL(inbuf,smb_com);
358 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
359 smb_fn_name(type), type, type));
361 return(ERROR(ERRSRV,ERRunknownsmb));
365 /****************************************************************************
366 reply to an ioctl
367 ****************************************************************************/
368 int reply_ioctl(connection_struct *conn,
369 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
371 DEBUG(3,("ignoring ioctl\n"));
372 #if 0
373 /* we just say it succeeds and hope its all OK.
374 some day it would be nice to interpret them individually */
375 return set_message(outbuf,1,0,True);
376 #else
377 return(ERROR(ERRSRV,ERRnosupport));
378 #endif
381 /****************************************************************************
382 always return an error: it's just a matter of which one...
383 ****************************************************************************/
384 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
385 char *smb_passwd, int smb_passlen,
386 char *smb_nt_passwd, int smb_nt_passlen)
388 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
389 if (lp_security() == SEC_USER)
391 smb_trust_acct = getsmbpwnam(user);
393 else
395 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
396 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
397 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
400 if (smb_trust_acct == NULL)
402 /* lkclXXXX: workstation entry doesn't exist */
403 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
404 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
405 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
407 else
409 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
411 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
412 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
413 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
416 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
418 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
419 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
420 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
423 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
425 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
426 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
427 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
430 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
432 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
433 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
434 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
437 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
439 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
440 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
441 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
445 /* don't know what to do: indicate logon failure */
446 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
447 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
450 /****************************************************************************
451 Check for a valid username and password in security=server mode.
452 ****************************************************************************/
454 static BOOL check_server_security(char *orig_user, char *domain,
455 char *smb_apasswd, int smb_apasslen,
456 char *smb_ntpasswd, int smb_ntpasslen)
458 if(lp_security() != SEC_SERVER)
459 return False;
461 return server_validate(orig_user, domain,
462 smb_apasswd, smb_apasslen,
463 smb_ntpasswd, smb_ntpasslen);
466 /****************************************************************************
467 Check for a valid username and password in security=domain mode.
468 ****************************************************************************/
470 static BOOL check_domain_security(char *orig_user, char *domain,
471 char *smb_apasswd, int smb_apasslen,
472 char *smb_ntpasswd, int smb_ntpasslen)
474 if(lp_security() != SEC_DOMAIN)
475 return False;
477 return domain_client_validate(orig_user, domain,
478 smb_apasswd, smb_apasslen,
479 smb_ntpasswd, smb_ntpasslen);
482 /****************************************************************************
483 reply to a session setup command
484 ****************************************************************************/
486 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
488 uint16 sess_vuid;
489 int gid;
490 int uid;
491 int smb_bufsize;
492 int smb_apasslen = 0;
493 pstring smb_apasswd;
494 int smb_ntpasslen = 0;
495 pstring smb_ntpasswd;
496 BOOL valid_nt_password = False;
497 pstring user;
498 pstring orig_user;
499 BOOL guest=False;
500 static BOOL done_sesssetup = False;
501 BOOL doencrypt = SMBENCRYPT();
502 char *domain = "";
504 *smb_apasswd = 0;
505 *smb_ntpasswd = 0;
507 smb_bufsize = SVAL(inbuf,smb_vwv2);
509 if (Protocol < PROTOCOL_NT1) {
510 smb_apasslen = SVAL(inbuf,smb_vwv7);
511 if (smb_apasslen > MAX_PASS_LEN)
513 overflow_attack(smb_apasslen);
516 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
517 smb_apasswd[smb_apasslen] = 0;
518 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
520 if (!doencrypt && (lp_security() != SEC_SERVER)) {
521 smb_apasslen = strlen(smb_apasswd);
523 } else {
524 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
525 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
526 enum remote_arch_types ra_type = get_remote_arch();
527 char *p = smb_buf(inbuf);
529 global_client_caps = IVAL(inbuf,smb_vwv11);
531 /* client_caps is used as final determination if client is NT or Win95.
532 This is needed to return the correct error codes in some
533 circumstances.
536 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
538 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
539 set_remote_arch( RA_WINNT);
540 else
541 set_remote_arch( RA_WIN95);
544 if (passlen1 != 24 && passlen2 != 24)
545 doencrypt = False;
547 if (passlen1 > MAX_PASS_LEN) {
548 overflow_attack(passlen1);
551 passlen1 = MIN(passlen1, MAX_PASS_LEN);
552 passlen2 = MIN(passlen2, MAX_PASS_LEN);
554 if(!doencrypt) {
555 /* both Win95 and WinNT stuff up the password lengths for
556 non-encrypting systems. Uggh.
558 if passlen1==24 its a win95 system, and its setting the
559 password length incorrectly. Luckily it still works with the
560 default code because Win95 will null terminate the password
561 anyway
563 if passlen1>0 and passlen2>0 then maybe its a NT box and its
564 setting passlen2 to some random value which really stuffs
565 things up. we need to fix that one. */
567 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
568 passlen2 = 0;
571 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
572 /* Save the lanman2 password and the NT md4 password. */
573 smb_apasslen = passlen1;
574 memcpy(smb_apasswd,p,smb_apasslen);
575 smb_apasswd[smb_apasslen] = 0;
576 smb_ntpasslen = passlen2;
577 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
578 smb_ntpasswd[smb_ntpasslen] = 0;
579 } else {
580 /* we use the first password that they gave */
581 smb_apasslen = passlen1;
582 StrnCpy(smb_apasswd,p,smb_apasslen);
584 /* trim the password */
585 smb_apasslen = strlen(smb_apasswd);
587 /* wfwg sometimes uses a space instead of a null */
588 if (strequal(smb_apasswd," ")) {
589 smb_apasslen = 0;
590 *smb_apasswd = 0;
594 p += passlen1 + passlen2;
595 fstrcpy(user,p); p = skip_string(p,1);
596 domain = p;
598 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
599 domain,skip_string(p,1),skip_string(p,2)));
603 DEBUG(3,("sesssetupX:name=[%s]\n",user));
605 /* If name ends in $ then I think it's asking about whether a */
606 /* computer with that name (minus the $) has access. For now */
607 /* say yes to everything ending in $. */
608 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
610 return session_trust_account(conn, inbuf, outbuf, user,
611 smb_apasswd, smb_apasslen,
612 smb_ntpasswd, smb_ntpasslen);
615 /* If no username is sent use the guest account */
616 if (!*user)
618 pstrcpy(user,lp_guestaccount(-1));
619 /* If no user and no password then set guest flag. */
620 if( *smb_apasswd == 0)
621 guest = True;
624 strlower(user);
627 * In share level security, only overwrite sesssetup_use if
628 * it's a non null-session share. Helps keep %U and %G
629 * working.
632 if((lp_security() != SEC_SHARE) || (*user && !guest))
633 pstrcpy(sesssetup_user,user);
635 reload_services(True);
638 * Save the username before mapping. We will use
639 * the original username sent to us for security=server
640 * and security=domain checking.
643 pstrcpy( orig_user, user);
646 * Pass the user through the NT -> unix user mapping
647 * function.
650 (void)map_username(user);
653 * Do any UNIX username case mangling.
655 (void)Get_Pwnam( user, True);
657 add_session_user(user);
660 * Check if the given username was the guest user with no password.
663 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
664 guest = True;
667 * Check with orig_user for security=server and
668 * security=domain.
671 if (!guest &&
672 !check_server_security(orig_user, domain,
673 smb_apasswd, smb_apasslen,
674 smb_ntpasswd, smb_ntpasslen) &&
675 !check_domain_security(orig_user, domain,
676 smb_apasswd, smb_apasslen,
677 smb_ntpasswd, smb_ntpasslen) &&
678 !check_hosts_equiv(user)
683 * If we get here then the user wasn't guest and the remote
684 * authentication methods failed. Check the authentication
685 * methods on this local server.
687 * If an NT password was supplied try and validate with that
688 * first. This is superior as the passwords are mixed case
689 * 128 length unicode.
692 if(smb_ntpasslen)
694 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
695 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
696 else
697 valid_nt_password = True;
700 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
702 if (lp_security() >= SEC_USER)
704 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
705 return(ERROR(ERRSRV,ERRbadpw));
707 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
709 if (Get_Pwnam(user,True))
710 return(ERROR(ERRSRV,ERRbadpw));
714 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
715 * Then always map to guest account - as done below.
719 if (*smb_apasswd || !Get_Pwnam(user,True))
720 pstrcpy(user,lp_guestaccount(-1));
721 DEBUG(3,("Registered username %s for guest access\n",user));
722 guest = True;
726 if (!Get_Pwnam(user,True)) {
727 DEBUG(3,("No such user %s - using guest account\n",user));
728 pstrcpy(user,lp_guestaccount(-1));
729 guest = True;
732 if (!strequal(user,lp_guestaccount(-1)) &&
733 lp_servicenumber(user) < 0)
735 int homes = lp_servicenumber(HOMES_NAME);
736 char *home = get_home_dir(user);
737 if (homes >= 0 && home)
738 lp_add_home(user,homes,home);
742 /* it's ok - setup a reply */
743 if (Protocol < PROTOCOL_NT1) {
744 set_message(outbuf,3,0,True);
745 } else {
746 char *p;
747 set_message(outbuf,3,3,True);
748 p = smb_buf(outbuf);
749 pstrcpy(p,"Unix"); p = skip_string(p,1);
750 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
751 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
752 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
753 /* perhaps grab OS version here?? */
756 /* Set the correct uid in the outgoing and incoming packets
757 We will use this on future requests to determine which
758 user we should become.
761 struct passwd *pw = Get_Pwnam(user,False);
762 if (!pw) {
763 DEBUG(1,("Username %s is invalid on this system\n",user));
764 return(ERROR(ERRSRV,ERRbadpw));
766 gid = pw->pw_gid;
767 uid = pw->pw_uid;
770 if (guest)
771 SSVAL(outbuf,smb_vwv2,1);
773 /* register the name and uid as being validated, so further connections
774 to a uid can get through without a password, on the same VC */
775 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
777 SSVAL(outbuf,smb_uid,sess_vuid);
778 SSVAL(inbuf,smb_uid,sess_vuid);
780 if (!done_sesssetup)
781 max_send = MIN(max_send,smb_bufsize);
783 DEBUG(6,("Client requested max send size of %d\n", max_send));
785 done_sesssetup = True;
787 return chain_reply(inbuf,outbuf,length,bufsize);
791 /****************************************************************************
792 reply to a chkpth
793 ****************************************************************************/
794 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
796 int outsize = 0;
797 int mode;
798 pstring name;
799 BOOL ok = False;
800 BOOL bad_path = False;
801 SMB_STRUCT_STAT st;
803 pstrcpy(name,smb_buf(inbuf) + 1);
804 unix_convert(name,conn,0,&bad_path,&st);
806 mode = SVAL(inbuf,smb_vwv0);
808 if (check_name(name,conn)) {
809 if(VALID_STAT(st))
810 ok = S_ISDIR(st.st_mode);
811 else
812 ok = dos_directory_exist(name,NULL);
815 if (!ok)
817 /* We special case this - as when a Windows machine
818 is parsing a path is steps through the components
819 one at a time - if a component fails it expects
820 ERRbadpath, not ERRbadfile.
822 if(errno == ENOENT)
824 unix_ERR_class = ERRDOS;
825 unix_ERR_code = ERRbadpath;
828 #if 0
829 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
830 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
831 (get_remote_arch() == RA_WINNT))
833 unix_ERR_class = ERRDOS;
834 unix_ERR_code = ERRbaddirectory;
836 #endif
838 return(UNIXERROR(ERRDOS,ERRbadpath));
841 outsize = set_message(outbuf,0,0,True);
843 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
845 return(outsize);
849 /****************************************************************************
850 reply to a getatr
851 ****************************************************************************/
852 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
854 pstring fname;
855 int outsize = 0;
856 SMB_STRUCT_STAT sbuf;
857 BOOL ok = False;
858 int mode=0;
859 SMB_OFF_T size=0;
860 time_t mtime=0;
861 BOOL bad_path = False;
863 pstrcpy(fname,smb_buf(inbuf) + 1);
865 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
866 under WfWg - weird! */
867 if (! (*fname))
869 mode = aHIDDEN | aDIR;
870 if (!CAN_WRITE(conn)) mode |= aRONLY;
871 size = 0;
872 mtime = 0;
873 ok = True;
875 else
877 unix_convert(fname,conn,0,&bad_path,&sbuf);
878 if (check_name(fname,conn))
880 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
882 mode = dos_mode(conn,fname,&sbuf);
883 size = sbuf.st_size;
884 mtime = sbuf.st_mtime;
885 if (mode & aDIR)
886 size = 0;
887 ok = True;
889 else
890 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
894 if (!ok)
896 if((errno == ENOENT) && bad_path)
898 unix_ERR_class = ERRDOS;
899 unix_ERR_code = ERRbadpath;
902 return(UNIXERROR(ERRDOS,ERRbadfile));
905 outsize = set_message(outbuf,10,0,True);
907 SSVAL(outbuf,smb_vwv0,mode);
908 if(lp_dos_filetime_resolution(SNUM(conn)) )
909 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
910 else
911 put_dos_date3(outbuf,smb_vwv1,mtime);
912 SIVAL(outbuf,smb_vwv3,(uint32)size);
914 if (Protocol >= PROTOCOL_NT1) {
915 char *p = strrchr(fname,'/');
916 uint16 flg2 = SVAL(outbuf,smb_flg2);
917 if (!p) p = fname;
918 if (!is_8_3(fname, True))
919 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
922 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
924 return(outsize);
928 /****************************************************************************
929 reply to a setatr
930 ****************************************************************************/
931 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
933 pstring fname;
934 int outsize = 0;
935 BOOL ok=False;
936 int mode;
937 time_t mtime;
938 SMB_STRUCT_STAT st;
939 BOOL bad_path = False;
941 pstrcpy(fname,smb_buf(inbuf) + 1);
942 unix_convert(fname,conn,0,&bad_path,&st);
944 mode = SVAL(inbuf,smb_vwv0);
945 mtime = make_unix_date3(inbuf+smb_vwv1);
947 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
948 mode |= aDIR;
949 if (check_name(fname,conn))
950 ok = (file_chmod(conn,fname,mode,NULL) == 0);
951 if (ok)
952 ok = set_filetime(conn,fname,mtime);
954 if (!ok)
956 if((errno == ENOENT) && bad_path)
958 unix_ERR_class = ERRDOS;
959 unix_ERR_code = ERRbadpath;
962 return(UNIXERROR(ERRDOS,ERRnoaccess));
965 outsize = set_message(outbuf,0,0,True);
967 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
969 return(outsize);
973 /****************************************************************************
974 reply to a dskattr
975 ****************************************************************************/
976 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
978 int outsize = 0;
979 SMB_BIG_UINT dfree,dsize,bsize;
981 sys_disk_free(".",&bsize,&dfree,&dsize);
983 outsize = set_message(outbuf,5,0,True);
985 SSVAL(outbuf,smb_vwv0,dsize);
986 SSVAL(outbuf,smb_vwv1,bsize/512);
987 SSVAL(outbuf,smb_vwv2,512);
988 SSVAL(outbuf,smb_vwv3,dfree);
990 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
992 return(outsize);
996 /****************************************************************************
997 reply to a search
998 Can be called from SMBsearch, SMBffirst or SMBfunique.
999 ****************************************************************************/
1000 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1002 pstring mask;
1003 pstring directory;
1004 pstring fname;
1005 SMB_OFF_T size;
1006 int mode;
1007 time_t date;
1008 int dirtype;
1009 int outsize = 0;
1010 int numentries = 0;
1011 BOOL finished = False;
1012 int maxentries;
1013 int i;
1014 char *p;
1015 BOOL ok = False;
1016 int status_len;
1017 char *path;
1018 char status[21];
1019 int dptr_num= -1;
1020 BOOL check_descend = False;
1021 BOOL expect_close = False;
1022 BOOL can_open = True;
1023 BOOL bad_path = False;
1025 *mask = *directory = *fname = 0;
1027 /* If we were called as SMBffirst then we must expect close. */
1028 if(CVAL(inbuf,smb_com) == SMBffirst)
1029 expect_close = True;
1031 outsize = set_message(outbuf,1,3,True);
1032 maxentries = SVAL(inbuf,smb_vwv0);
1033 dirtype = SVAL(inbuf,smb_vwv1);
1034 path = smb_buf(inbuf) + 1;
1035 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1038 /* dirtype &= ~aDIR; */
1040 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1043 if (status_len == 0)
1045 pstring dir2;
1047 pstrcpy(directory,smb_buf(inbuf)+1);
1048 pstrcpy(dir2,smb_buf(inbuf)+1);
1049 unix_convert(directory,conn,0,&bad_path,NULL);
1050 unix_format(dir2);
1052 if (!check_name(directory,conn))
1053 can_open = False;
1055 p = strrchr(dir2,'/');
1056 if (p == NULL)
1058 pstrcpy(mask,dir2);
1059 *dir2 = 0;
1061 else
1063 *p = 0;
1064 pstrcpy(mask,p+1);
1067 p = strrchr(directory,'/');
1068 if (!p)
1069 *directory = 0;
1070 else
1071 *p = 0;
1073 if (strlen(directory) == 0)
1074 pstrcpy(directory,"./");
1075 bzero(status,21);
1076 CVAL(status,0) = dirtype;
1078 else
1080 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1081 memcpy(mask,status+1,11);
1082 mask[11] = 0;
1083 dirtype = CVAL(status,0) & 0x1F;
1084 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1085 if (!conn->dirptr)
1086 goto SearchEmpty;
1087 string_set(&conn->dirpath,dptr_path(dptr_num));
1088 if (!case_sensitive)
1089 strnorm(mask);
1092 /* turn strings of spaces into a . */
1094 trim_string(mask,NULL," ");
1095 if ((p = strrchr(mask,' ')))
1097 fstring ext;
1098 fstrcpy(ext,p+1);
1099 *p = 0;
1100 trim_string(mask,NULL," ");
1101 pstrcat(mask,".");
1102 pstrcat(mask,ext);
1106 /* Convert the formatted mask. (This code lives in trans2.c) */
1107 mask_convert(mask);
1110 int skip;
1111 p = mask;
1112 while(*p)
1114 if((skip = skip_multibyte_char( *p )) != 0 )
1116 p += skip;
1118 else
1120 if (*p != '?' && *p != '*' && !isdoschar(*p))
1122 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1123 *p = '?';
1125 p++;
1130 if (!strchr(mask,'.') && strlen(mask)>8)
1132 fstring tmp;
1133 fstrcpy(tmp,&mask[8]);
1134 mask[8] = '.';
1135 mask[9] = 0;
1136 pstrcat(mask,tmp);
1139 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1141 if (can_open)
1143 p = smb_buf(outbuf) + 3;
1145 ok = True;
1147 if (status_len == 0)
1149 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1150 if (dptr_num < 0)
1152 if(dptr_num == -2)
1154 if((errno == ENOENT) && bad_path)
1156 unix_ERR_class = ERRDOS;
1157 unix_ERR_code = ERRbadpath;
1159 return (UNIXERROR(ERRDOS,ERRnofids));
1161 return(ERROR(ERRDOS,ERRnofids));
1165 DEBUG(4,("dptr_num is %d\n",dptr_num));
1167 if (ok)
1169 if ((dirtype&0x1F) == aVOLID)
1171 memcpy(p,status,21);
1172 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1173 dptr_fill(p+12,dptr_num);
1174 if (dptr_zero(p+12) && (status_len==0))
1175 numentries = 1;
1176 else
1177 numentries = 0;
1178 p += DIR_STRUCT_SIZE;
1180 else
1182 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1183 conn->dirpath,lp_dontdescend(SNUM(conn))));
1184 if (in_list(conn->dirpath,
1185 lp_dontdescend(SNUM(conn)),True))
1186 check_descend = True;
1188 for (i=numentries;(i<maxentries) && !finished;i++)
1190 finished =
1191 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1192 if (!finished)
1194 memcpy(p,status,21);
1195 make_dir_struct(p,mask,fname,size,mode,date);
1196 dptr_fill(p+12,dptr_num);
1197 numentries++;
1199 p += DIR_STRUCT_SIZE;
1206 SearchEmpty:
1208 if (numentries == 0 || !ok)
1210 CVAL(outbuf,smb_rcls) = ERRDOS;
1211 SSVAL(outbuf,smb_err,ERRnofiles);
1214 /* If we were called as SMBffirst with smb_search_id == NULL
1215 and no entries were found then return error and close dirptr
1216 (X/Open spec) */
1218 if(ok && expect_close && numentries == 0 && status_len == 0)
1220 CVAL(outbuf,smb_rcls) = ERRDOS;
1221 SSVAL(outbuf,smb_err,ERRnofiles);
1222 /* Also close the dptr - we know it's gone */
1223 dptr_close(dptr_num);
1226 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1227 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1228 dptr_close(dptr_num);
1230 SSVAL(outbuf,smb_vwv0,numentries);
1231 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1232 CVAL(smb_buf(outbuf),0) = 5;
1233 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1235 if (Protocol >= PROTOCOL_NT1) {
1236 uint16 flg2 = SVAL(outbuf,smb_flg2);
1237 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1240 outsize += DIR_STRUCT_SIZE*numentries;
1241 smb_setlen(outbuf,outsize - 4);
1243 if ((! *directory) && dptr_path(dptr_num))
1244 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1246 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1247 smb_fn_name(CVAL(inbuf,smb_com)),
1248 mask, directory, dirtype, numentries, maxentries ) );
1250 return(outsize);
1254 /****************************************************************************
1255 reply to a fclose (stop directory search)
1256 ****************************************************************************/
1257 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1259 int outsize = 0;
1260 int status_len;
1261 char *path;
1262 char status[21];
1263 int dptr_num= -1;
1265 outsize = set_message(outbuf,1,0,True);
1266 path = smb_buf(inbuf) + 1;
1267 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1270 if (status_len == 0)
1271 return(ERROR(ERRSRV,ERRsrverror));
1273 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1275 if(dptr_fetch(status+12,&dptr_num)) {
1276 /* Close the dptr - we know it's gone */
1277 dptr_close(dptr_num);
1280 SSVAL(outbuf,smb_vwv0,0);
1282 DEBUG(3,("search close\n"));
1284 return(outsize);
1288 /****************************************************************************
1289 reply to an open
1290 ****************************************************************************/
1292 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1294 pstring fname;
1295 int outsize = 0;
1296 int fmode=0;
1297 int share_mode;
1298 SMB_OFF_T size = 0;
1299 time_t mtime=0;
1300 mode_t unixmode;
1301 int rmode=0;
1302 SMB_STRUCT_STAT sbuf;
1303 BOOL bad_path = False;
1304 files_struct *fsp;
1305 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1307 share_mode = SVAL(inbuf,smb_vwv0);
1309 pstrcpy(fname,smb_buf(inbuf)+1);
1310 unix_convert(fname,conn,0,&bad_path,NULL);
1312 fsp = file_new();
1313 if (!fsp)
1314 return(ERROR(ERRSRV,ERRnofids));
1316 if (!check_name(fname,conn))
1318 if((errno == ENOENT) && bad_path)
1320 unix_ERR_class = ERRDOS;
1321 unix_ERR_code = ERRbadpath;
1323 file_free(fsp);
1324 return(UNIXERROR(ERRDOS,ERRnoaccess));
1327 unixmode = unix_mode(conn,aARCH);
1329 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1330 unixmode, oplock_request,&rmode,NULL);
1332 if (!fsp->open)
1334 if((errno == ENOENT) && bad_path)
1336 unix_ERR_class = ERRDOS;
1337 unix_ERR_code = ERRbadpath;
1339 file_free(fsp);
1340 return(UNIXERROR(ERRDOS,ERRnoaccess));
1343 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1344 close_file(fsp,False);
1345 return(ERROR(ERRDOS,ERRnoaccess));
1348 size = sbuf.st_size;
1349 fmode = dos_mode(conn,fname,&sbuf);
1350 mtime = sbuf.st_mtime;
1352 if (fmode & aDIR) {
1353 DEBUG(3,("attempt to open a directory %s\n",fname));
1354 close_file(fsp,False);
1355 return(ERROR(ERRDOS,ERRnoaccess));
1358 outsize = set_message(outbuf,7,0,True);
1359 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1360 SSVAL(outbuf,smb_vwv1,fmode);
1361 if(lp_dos_filetime_resolution(SNUM(conn)) )
1362 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1363 else
1364 put_dos_date3(outbuf,smb_vwv2,mtime);
1365 SIVAL(outbuf,smb_vwv4,(uint32)size);
1366 SSVAL(outbuf,smb_vwv6,rmode);
1368 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1369 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1372 if(fsp->granted_oplock)
1373 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1374 return(outsize);
1378 /****************************************************************************
1379 reply to an open and X
1380 ****************************************************************************/
1381 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1383 pstring fname;
1384 int smb_mode = SVAL(inbuf,smb_vwv3);
1385 int smb_attr = SVAL(inbuf,smb_vwv5);
1386 /* Breakout the oplock request bits so we can set the
1387 reply bits separately. */
1388 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1389 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1390 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1391 #if 0
1392 int open_flags = SVAL(inbuf,smb_vwv2);
1393 int smb_sattr = SVAL(inbuf,smb_vwv4);
1394 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1395 #endif
1396 int smb_ofun = SVAL(inbuf,smb_vwv8);
1397 mode_t unixmode;
1398 SMB_OFF_T size=0;
1399 int fmode=0,mtime=0,rmode=0;
1400 SMB_STRUCT_STAT sbuf;
1401 int smb_action = 0;
1402 BOOL bad_path = False;
1403 files_struct *fsp;
1405 /* If it's an IPC, pass off the pipe handler. */
1406 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1408 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1411 /* XXXX we need to handle passed times, sattr and flags */
1413 pstrcpy(fname,smb_buf(inbuf));
1414 unix_convert(fname,conn,0,&bad_path,NULL);
1416 fsp = file_new();
1417 if (!fsp)
1418 return(ERROR(ERRSRV,ERRnofids));
1420 if (!check_name(fname,conn))
1422 if((errno == ENOENT) && bad_path)
1424 unix_ERR_class = ERRDOS;
1425 unix_ERR_code = ERRbadpath;
1427 file_free(fsp);
1428 return(UNIXERROR(ERRDOS,ERRnoaccess));
1431 unixmode = unix_mode(conn,smb_attr | aARCH);
1433 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1434 oplock_request, &rmode,&smb_action);
1436 if (!fsp->open)
1438 if((errno == ENOENT) && bad_path)
1440 unix_ERR_class = ERRDOS;
1441 unix_ERR_code = ERRbadpath;
1443 file_free(fsp);
1444 return(UNIXERROR(ERRDOS,ERRnoaccess));
1447 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1448 close_file(fsp,False);
1449 return(ERROR(ERRDOS,ERRnoaccess));
1452 size = sbuf.st_size;
1453 fmode = dos_mode(conn,fname,&sbuf);
1454 mtime = sbuf.st_mtime;
1455 if (fmode & aDIR) {
1456 close_file(fsp,False);
1457 return(ERROR(ERRDOS,ERRnoaccess));
1460 /* If the caller set the extended oplock request bit
1461 and we granted one (by whatever means) - set the
1462 correct bit for extended oplock reply.
1465 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1466 smb_action |= EXTENDED_OPLOCK_GRANTED;
1469 if(ex_oplock_request && fsp->granted_oplock) {
1470 smb_action |= EXTENDED_OPLOCK_GRANTED;
1473 /* If the caller set the core oplock request bit
1474 and we granted one (by whatever means) - set the
1475 correct bit for core oplock reply.
1478 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1479 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1482 if(core_oplock_request && fsp->granted_oplock) {
1483 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1486 set_message(outbuf,15,0,True);
1487 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1488 SSVAL(outbuf,smb_vwv3,fmode);
1489 if(lp_dos_filetime_resolution(SNUM(conn)) )
1490 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1491 else
1492 put_dos_date3(outbuf,smb_vwv4,mtime);
1493 SIVAL(outbuf,smb_vwv6,(uint32)size);
1494 SSVAL(outbuf,smb_vwv8,rmode);
1495 SSVAL(outbuf,smb_vwv11,smb_action);
1497 return chain_reply(inbuf,outbuf,length,bufsize);
1501 /****************************************************************************
1502 reply to a SMBulogoffX
1503 ****************************************************************************/
1504 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1506 uint16 vuid = SVAL(inbuf,smb_uid);
1507 user_struct *vuser = get_valid_user_struct(vuid);
1509 if(vuser == 0) {
1510 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1513 /* in user level security we are supposed to close any files
1514 open by this user */
1515 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1516 file_close_user(vuid);
1519 invalidate_vuid(vuid);
1521 set_message(outbuf,2,0,True);
1523 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1525 return chain_reply(inbuf,outbuf,length,bufsize);
1529 /****************************************************************************
1530 reply to a mknew or a create
1531 ****************************************************************************/
1532 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1534 pstring fname;
1535 int com;
1536 int outsize = 0;
1537 int createmode;
1538 mode_t unixmode;
1539 int ofun = 0;
1540 BOOL bad_path = False;
1541 files_struct *fsp;
1542 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1544 com = SVAL(inbuf,smb_com);
1546 createmode = SVAL(inbuf,smb_vwv0);
1547 pstrcpy(fname,smb_buf(inbuf)+1);
1548 unix_convert(fname,conn,0,&bad_path,NULL);
1550 if (createmode & aVOLID)
1552 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1555 unixmode = unix_mode(conn,createmode);
1557 fsp = file_new();
1558 if (!fsp)
1559 return(ERROR(ERRSRV,ERRnofids));
1561 if (!check_name(fname,conn))
1563 if((errno == ENOENT) && bad_path)
1565 unix_ERR_class = ERRDOS;
1566 unix_ERR_code = ERRbadpath;
1568 file_free(fsp);
1569 return(UNIXERROR(ERRDOS,ERRnoaccess));
1572 if(com == SMBmknew)
1574 /* We should fail if file exists. */
1575 ofun = 0x10;
1577 else
1579 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1580 ofun = 0x12;
1583 /* Open file in dos compatibility share mode. */
1584 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1585 ofun, unixmode, oplock_request, NULL, NULL);
1587 if (!fsp->open)
1589 if((errno == ENOENT) && bad_path)
1591 unix_ERR_class = ERRDOS;
1592 unix_ERR_code = ERRbadpath;
1594 file_free(fsp);
1595 return(UNIXERROR(ERRDOS,ERRnoaccess));
1598 outsize = set_message(outbuf,1,0,True);
1599 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1601 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1602 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1605 if(fsp->granted_oplock)
1606 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1608 DEBUG( 2, ( "new file %s\n", fname ) );
1609 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1610 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1612 return(outsize);
1616 /****************************************************************************
1617 reply to a create temporary file
1618 ****************************************************************************/
1619 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1621 pstring fname;
1622 pstring fname2;
1623 int outsize = 0;
1624 int createmode;
1625 mode_t unixmode;
1626 BOOL bad_path = False;
1627 files_struct *fsp;
1628 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1630 createmode = SVAL(inbuf,smb_vwv0);
1631 pstrcpy(fname,smb_buf(inbuf)+1);
1632 pstrcat(fname,"/TMXXXXXX");
1633 unix_convert(fname,conn,0,&bad_path,NULL);
1635 unixmode = unix_mode(conn,createmode);
1637 fsp = file_new();
1638 if (fsp)
1639 return(ERROR(ERRSRV,ERRnofids));
1641 if (!check_name(fname,conn))
1643 if((errno == ENOENT) && bad_path)
1645 unix_ERR_class = ERRDOS;
1646 unix_ERR_code = ERRbadpath;
1648 file_free(fsp);
1649 return(UNIXERROR(ERRDOS,ERRnoaccess));
1652 pstrcpy(fname2,(char *)mktemp(fname));
1654 /* Open file in dos compatibility share mode. */
1655 /* We should fail if file exists. */
1656 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1657 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1659 if (!fsp->open)
1661 if((errno == ENOENT) && bad_path)
1663 unix_ERR_class = ERRDOS;
1664 unix_ERR_code = ERRbadpath;
1666 file_free(fsp);
1667 return(UNIXERROR(ERRDOS,ERRnoaccess));
1670 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1671 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1672 CVAL(smb_buf(outbuf),0) = 4;
1673 pstrcpy(smb_buf(outbuf) + 1,fname2);
1675 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1676 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1679 if(fsp->granted_oplock)
1680 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1682 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1683 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1684 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1686 return(outsize);
1690 /*******************************************************************
1691 check if a user is allowed to delete a file
1692 ********************************************************************/
1693 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1695 SMB_STRUCT_STAT sbuf;
1696 int fmode;
1698 if (!CAN_WRITE(conn)) return(False);
1700 if (dos_lstat(fname,&sbuf) != 0) return(False);
1701 fmode = dos_mode(conn,fname,&sbuf);
1702 if (fmode & aDIR) return(False);
1703 if (!lp_delete_readonly(SNUM(conn))) {
1704 if (fmode & aRONLY) return(False);
1706 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1707 return(False);
1708 if (!check_file_sharing(conn,fname,False)) return(False);
1709 return(True);
1712 /****************************************************************************
1713 reply to a unlink
1714 ****************************************************************************/
1715 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1717 int outsize = 0;
1718 pstring name;
1719 int dirtype;
1720 pstring directory;
1721 pstring mask;
1722 char *p;
1723 int count=0;
1724 int error = ERRnoaccess;
1725 BOOL has_wild;
1726 BOOL exists=False;
1727 BOOL bad_path = False;
1729 *directory = *mask = 0;
1731 dirtype = SVAL(inbuf,smb_vwv0);
1733 pstrcpy(name,smb_buf(inbuf) + 1);
1735 DEBUG(3,("reply_unlink : %s\n",name));
1737 unix_convert(name,conn,0,&bad_path,NULL);
1739 p = strrchr(name,'/');
1740 if (!p) {
1741 pstrcpy(directory,"./");
1742 pstrcpy(mask,name);
1743 } else {
1744 *p = 0;
1745 pstrcpy(directory,name);
1746 pstrcpy(mask,p+1);
1749 if (is_mangled(mask))
1750 check_mangled_cache( mask );
1752 has_wild = strchr(mask,'*') || strchr(mask,'?');
1754 if (!has_wild) {
1755 pstrcat(directory,"/");
1756 pstrcat(directory,mask);
1757 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1758 count++;
1759 if (!count)
1760 exists = dos_file_exist(directory,NULL);
1761 } else {
1762 void *dirptr = NULL;
1763 char *dname;
1765 if (check_name(directory,conn))
1766 dirptr = OpenDir(conn, directory, True);
1768 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1769 the pattern matches against the long name, otherwise the short name
1770 We don't implement this yet XXXX
1773 if (dirptr)
1775 error = ERRbadfile;
1777 if (strequal(mask,"????????.???"))
1778 pstrcpy(mask,"*");
1780 while ((dname = ReadDirName(dirptr)))
1782 pstring fname;
1783 pstrcpy(fname,dname);
1785 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1787 error = ERRnoaccess;
1788 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1789 if (!can_delete(fname,conn,dirtype)) continue;
1790 if (!dos_unlink(fname)) count++;
1791 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1793 CloseDir(dirptr);
1797 if (count == 0) {
1798 if (exists)
1799 return(ERROR(ERRDOS,error));
1800 else
1802 if((errno == ENOENT) && bad_path)
1804 unix_ERR_class = ERRDOS;
1805 unix_ERR_code = ERRbadpath;
1807 return(UNIXERROR(ERRDOS,error));
1811 outsize = set_message(outbuf,0,0,True);
1813 return(outsize);
1817 /****************************************************************************
1818 reply to a readbraw (core+ protocol)
1819 ****************************************************************************/
1820 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1822 size_t maxcount,mincount;
1823 size_t nread = 0;
1824 SMB_OFF_T startpos;
1825 char *header = outbuf;
1826 ssize_t ret=0;
1827 files_struct *fsp;
1830 * Special check if an oplock break has been issued
1831 * and the readraw request croses on the wire, we must
1832 * return a zero length response here.
1835 if(global_oplock_break)
1837 _smb_setlen(header,0);
1838 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1839 DEBUG(5,("readbraw - oplock break finished\n"));
1840 return -1;
1843 fsp = file_fsp(inbuf,smb_vwv0);
1845 startpos = IVAL(inbuf,smb_vwv1);
1846 #ifdef LARGE_SMB_OFF_T
1847 if(CVAL(inbuf,smb_wct) == 10) {
1849 * This is a large offset (64 bit) read.
1851 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1852 if(startpos < 0) {
1853 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1854 (double)startpos ));
1855 _smb_setlen(header,0);
1856 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1857 return(-1);
1860 #endif /* LARGE_SMB_OFF_T */
1861 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1862 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1864 /* ensure we don't overrun the packet size */
1865 maxcount = MIN(65535,maxcount);
1866 maxcount = MAX(mincount,maxcount);
1868 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1869 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1870 _smb_setlen(header,0);
1871 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1872 return(-1);
1875 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1877 SMB_OFF_T size = fsp->size;
1878 SMB_OFF_T sizeneeded = startpos + maxcount;
1880 if (size < sizeneeded)
1882 SMB_STRUCT_STAT st;
1883 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1884 size = st.st_size;
1885 if (!fsp->can_write)
1886 fsp->size = size;
1889 nread = MIN(maxcount,(size - startpos));
1892 if (nread < mincount)
1893 nread = 0;
1895 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1896 fsp->fnum, (double)startpos,
1897 maxcount, mincount, nread ) );
1899 #if UNSAFE_READRAW
1901 BOOL seek_fail = False;
1902 int predict=0;
1903 _smb_setlen(header,nread);
1905 #if USE_READ_PREDICTION
1906 if (!fsp->can_write)
1907 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1908 #endif /* USE_READ_PREDICTION */
1910 if ((nread-predict) > 0) {
1911 if(seek_file(fsp,startpos + predict) == -1) {
1912 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1913 ret = 0;
1914 seek_fail = True;
1918 if(!seek_fail)
1919 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1920 (SMB_OFF_T)(nread-predict),header,4+predict,
1921 startpos+predict);
1924 if (ret != nread+4)
1925 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1926 fsp->fsp_name,startpos,nread,ret));
1928 #else /* UNSAFE_READRAW */
1929 ret = read_file(fsp,header+4,startpos,nread);
1930 if (ret < mincount) ret = 0;
1932 _smb_setlen(header,ret);
1933 transfer_file(0,Client,0,header,4+ret,0);
1934 #endif /* UNSAFE_READRAW */
1936 DEBUG(5,("readbraw finished\n"));
1937 return -1;
1941 /****************************************************************************
1942 reply to a lockread (core+ protocol)
1943 ****************************************************************************/
1944 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1946 ssize_t nread = -1;
1947 char *data;
1948 int outsize = 0;
1949 SMB_OFF_T startpos;
1950 size_t numtoread;
1951 int eclass;
1952 uint32 ecode;
1953 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1955 CHECK_FSP(fsp,conn);
1956 CHECK_READ(fsp);
1957 CHECK_ERROR(fsp);
1959 numtoread = SVAL(inbuf,smb_vwv1);
1960 startpos = IVAL(inbuf,smb_vwv2);
1962 outsize = set_message(outbuf,5,3,True);
1963 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1964 data = smb_buf(outbuf) + 3;
1966 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1967 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1969 * A blocking lock was requested. Package up
1970 * this smb into a queued request and push it
1971 * onto the blocking lock queue.
1973 if(push_blocking_lock_request(inbuf, length, -1, 0))
1974 return -1;
1976 return (ERROR(eclass,ecode));
1979 nread = read_file(fsp,data,startpos,numtoread);
1981 if (nread < 0)
1982 return(UNIXERROR(ERRDOS,ERRnoaccess));
1984 outsize += nread;
1985 SSVAL(outbuf,smb_vwv0,nread);
1986 SSVAL(outbuf,smb_vwv5,nread+3);
1987 SSVAL(smb_buf(outbuf),1,nread);
1989 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1990 fsp->fnum, numtoread, nread ) );
1992 return(outsize);
1996 /****************************************************************************
1997 reply to a read
1998 ****************************************************************************/
1999 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2001 size_t numtoread;
2002 ssize_t nread = 0;
2003 char *data;
2004 SMB_OFF_T startpos;
2005 int outsize = 0;
2006 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2008 CHECK_FSP(fsp,conn);
2009 CHECK_READ(fsp);
2010 CHECK_ERROR(fsp);
2012 numtoread = SVAL(inbuf,smb_vwv1);
2013 startpos = IVAL(inbuf,smb_vwv2);
2015 outsize = set_message(outbuf,5,3,True);
2016 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2017 data = smb_buf(outbuf) + 3;
2019 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2020 return(ERROR(ERRDOS,ERRlock));
2022 if (numtoread > 0)
2023 nread = read_file(fsp,data,startpos,numtoread);
2025 if (nread < 0)
2026 return(UNIXERROR(ERRDOS,ERRnoaccess));
2028 outsize += nread;
2029 SSVAL(outbuf,smb_vwv0,nread);
2030 SSVAL(outbuf,smb_vwv5,nread+3);
2031 CVAL(smb_buf(outbuf),0) = 1;
2032 SSVAL(smb_buf(outbuf),1,nread);
2034 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2035 fsp->fnum, numtoread, nread ) );
2037 return(outsize);
2041 /****************************************************************************
2042 reply to a read and X
2043 ****************************************************************************/
2044 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2046 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2047 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2048 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2049 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2050 ssize_t nread = -1;
2051 char *data;
2053 /* If it's an IPC, pass off the pipe handler. */
2054 if (IS_IPC(conn))
2055 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2057 CHECK_FSP(fsp,conn);
2058 CHECK_READ(fsp);
2059 CHECK_ERROR(fsp);
2061 set_message(outbuf,12,0,True);
2062 data = smb_buf(outbuf);
2064 #ifdef LARGE_SMB_OFF_T
2065 if(CVAL(inbuf,smb_wct) == 12) {
2067 * This is a large offset (64 bit) read.
2069 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2071 #endif /* LARGE_SMB_OFF_T */
2073 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2074 return(ERROR(ERRDOS,ERRlock));
2075 nread = read_file(fsp,data,startpos,smb_maxcnt);
2077 if (nread < 0)
2078 return(UNIXERROR(ERRDOS,ERRnoaccess));
2080 SSVAL(outbuf,smb_vwv5,nread);
2081 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2082 SSVAL(smb_buf(outbuf),-2,nread);
2084 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2085 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2087 return chain_reply(inbuf,outbuf,length,bufsize);
2090 /****************************************************************************
2091 reply to a writebraw (core+ or LANMAN1.0 protocol)
2092 ****************************************************************************/
2093 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2095 ssize_t nwritten=0;
2096 ssize_t total_written=0;
2097 size_t numtowrite=0;
2098 size_t tcount;
2099 SMB_OFF_T startpos;
2100 char *data=NULL;
2101 BOOL write_through;
2102 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2103 int outsize = 0;
2105 CHECK_FSP(fsp,conn);
2106 CHECK_WRITE(fsp);
2107 CHECK_ERROR(fsp);
2109 tcount = IVAL(inbuf,smb_vwv1);
2110 startpos = IVAL(inbuf,smb_vwv3);
2111 write_through = BITSETW(inbuf+smb_vwv7,0);
2113 /* We have to deal with slightly different formats depending
2114 on whether we are using the core+ or lanman1.0 protocol */
2115 if(Protocol <= PROTOCOL_COREPLUS) {
2116 numtowrite = SVAL(smb_buf(inbuf),-2);
2117 data = smb_buf(inbuf);
2118 } else {
2119 numtowrite = SVAL(inbuf,smb_vwv10);
2120 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2123 /* force the error type */
2124 CVAL(inbuf,smb_com) = SMBwritec;
2125 CVAL(outbuf,smb_com) = SMBwritec;
2127 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2128 return(ERROR(ERRDOS,ERRlock));
2130 if (seek_file(fsp,startpos) == -1) {
2131 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2132 return(UNIXERROR(ERRDOS,ERRnoaccess));
2135 if (numtowrite>0)
2136 nwritten = write_file(fsp,data,numtowrite);
2138 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2139 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2141 if (nwritten < numtowrite)
2142 return(UNIXERROR(ERRHRD,ERRdiskfull));
2144 total_written = nwritten;
2146 /* Return a message to the redirector to tell it
2147 to send more bytes */
2148 CVAL(outbuf,smb_com) = SMBwritebraw;
2149 SSVALS(outbuf,smb_vwv0,-1);
2150 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2151 send_smb(Client,outbuf);
2153 /* Now read the raw data into the buffer and write it */
2154 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2155 exit_server("secondary writebraw failed");
2158 /* Even though this is not an smb message, smb_len
2159 returns the generic length of an smb message */
2160 numtowrite = smb_len(inbuf);
2162 if (tcount > nwritten+numtowrite) {
2163 DEBUG(3,("Client overestimated the write %d %d %d\n",
2164 tcount,nwritten,numtowrite));
2167 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2168 startpos+nwritten);
2169 total_written += nwritten;
2171 /* Set up outbuf to return the correct return */
2172 outsize = set_message(outbuf,1,0,True);
2173 CVAL(outbuf,smb_com) = SMBwritec;
2174 SSVAL(outbuf,smb_vwv0,total_written);
2176 if (nwritten < (ssize_t)numtowrite) {
2177 CVAL(outbuf,smb_rcls) = ERRHRD;
2178 SSVAL(outbuf,smb_err,ERRdiskfull);
2181 if (lp_syncalways(SNUM(conn)) || write_through)
2182 sync_file(conn,fsp);
2184 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2185 fsp->fnum, (double)startpos, numtowrite, total_written));
2187 /* we won't return a status if write through is not selected - this
2188 follows what WfWg does */
2189 if (!write_through && total_written==tcount)
2190 return(-1);
2192 return(outsize);
2195 /****************************************************************************
2196 reply to a writeunlock (core+)
2197 ****************************************************************************/
2198 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2200 ssize_t nwritten = -1;
2201 size_t numtowrite;
2202 SMB_OFF_T startpos;
2203 char *data;
2204 int eclass;
2205 uint32 ecode;
2206 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2207 int outsize = 0;
2209 CHECK_FSP(fsp,conn);
2210 CHECK_WRITE(fsp);
2211 CHECK_ERROR(fsp);
2213 numtowrite = SVAL(inbuf,smb_vwv1);
2214 startpos = IVAL(inbuf,smb_vwv2);
2215 data = smb_buf(inbuf) + 3;
2217 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2218 return(ERROR(ERRDOS,ERRlock));
2220 if(seek_file(fsp,startpos) == -1)
2221 return(UNIXERROR(ERRDOS,ERRnoaccess));
2223 /* The special X/Open SMB protocol handling of
2224 zero length writes is *NOT* done for
2225 this call */
2226 if(numtowrite == 0)
2227 nwritten = 0;
2228 else
2229 nwritten = write_file(fsp,data,numtowrite);
2231 if (lp_syncalways(SNUM(conn)))
2232 sync_file(conn,fsp);
2234 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2235 return(UNIXERROR(ERRDOS,ERRnoaccess));
2237 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2238 return(ERROR(eclass,ecode));
2240 outsize = set_message(outbuf,1,0,True);
2242 SSVAL(outbuf,smb_vwv0,nwritten);
2244 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2245 fsp->fnum, numtowrite, nwritten ) );
2247 return(outsize);
2250 /****************************************************************************
2251 reply to a write
2252 ****************************************************************************/
2253 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2255 size_t numtowrite;
2256 ssize_t nwritten = -1;
2257 SMB_OFF_T startpos;
2258 char *data;
2259 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2260 int outsize = 0;
2262 CHECK_FSP(fsp,conn);
2263 CHECK_WRITE(fsp);
2264 CHECK_ERROR(fsp);
2266 numtowrite = SVAL(inbuf,smb_vwv1);
2267 startpos = IVAL(inbuf,smb_vwv2);
2268 data = smb_buf(inbuf) + 3;
2270 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2271 return(ERROR(ERRDOS,ERRlock));
2273 if(seek_file(fsp,startpos) == -1)
2274 return(UNIXERROR(ERRDOS,ERRnoaccess));
2276 /* X/Open SMB protocol says that if smb_vwv1 is
2277 zero then the file size should be extended or
2278 truncated to the size given in smb_vwv[2-3] */
2279 if(numtowrite == 0)
2280 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2281 else
2282 nwritten = write_file(fsp,data,numtowrite);
2284 if (lp_syncalways(SNUM(conn)))
2285 sync_file(conn,fsp);
2287 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2288 return(UNIXERROR(ERRDOS,ERRnoaccess));
2290 outsize = set_message(outbuf,1,0,True);
2292 SSVAL(outbuf,smb_vwv0,nwritten);
2294 if (nwritten < (ssize_t)numtowrite) {
2295 CVAL(outbuf,smb_rcls) = ERRHRD;
2296 SSVAL(outbuf,smb_err,ERRdiskfull);
2299 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2300 fsp->fnum, numtowrite, nwritten));
2302 return(outsize);
2306 /****************************************************************************
2307 reply to a write and X
2308 ****************************************************************************/
2309 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2311 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2312 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2313 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2314 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2315 ssize_t nwritten = -1;
2316 int smb_doff = SVAL(inbuf,smb_vwv11);
2317 char *data;
2319 /* If it's an IPC, pass off the pipe handler. */
2320 if (IS_IPC(conn))
2321 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2323 CHECK_FSP(fsp,conn);
2324 CHECK_WRITE(fsp);
2325 CHECK_ERROR(fsp);
2327 data = smb_base(inbuf) + smb_doff;
2329 #ifdef LARGE_SMB_OFF_T
2330 if(CVAL(inbuf,smb_wct) == 14) {
2332 * This is a large offset (64 bit) write.
2334 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2336 #endif /* LARGE_SMB_OFF_T */
2338 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2339 return(ERROR(ERRDOS,ERRlock));
2341 if(seek_file(fsp,startpos) == -1)
2342 return(UNIXERROR(ERRDOS,ERRnoaccess));
2344 /* X/Open SMB protocol says that, unlike SMBwrite
2345 if the length is zero then NO truncation is
2346 done, just a write of zero. To truncate a file,
2347 use SMBwrite. */
2348 if(numtowrite == 0)
2349 nwritten = 0;
2350 else
2351 nwritten = write_file(fsp,data,numtowrite);
2353 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2354 return(UNIXERROR(ERRDOS,ERRnoaccess));
2356 set_message(outbuf,6,0,True);
2358 SSVAL(outbuf,smb_vwv2,nwritten);
2360 if (nwritten < (ssize_t)numtowrite) {
2361 CVAL(outbuf,smb_rcls) = ERRHRD;
2362 SSVAL(outbuf,smb_err,ERRdiskfull);
2365 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2366 fsp->fnum, numtowrite, nwritten));
2368 if (lp_syncalways(SNUM(conn)) || write_through)
2369 sync_file(conn,fsp);
2371 return chain_reply(inbuf,outbuf,length,bufsize);
2375 /****************************************************************************
2376 reply to a lseek
2377 ****************************************************************************/
2378 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2380 SMB_OFF_T startpos;
2381 SMB_OFF_T res= -1;
2382 int mode,umode;
2383 int outsize = 0;
2384 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2386 CHECK_FSP(fsp,conn);
2387 CHECK_ERROR(fsp);
2389 mode = SVAL(inbuf,smb_vwv1) & 3;
2390 startpos = IVAL(inbuf,smb_vwv2);
2392 switch (mode & 3)
2394 case 0: umode = SEEK_SET; break;
2395 case 1: umode = SEEK_CUR; break;
2396 case 2: umode = SEEK_END; break;
2397 default:
2398 umode = SEEK_SET; break;
2401 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2402 return(UNIXERROR(ERRDOS,ERRnoaccess));
2404 fsp->pos = res;
2406 outsize = set_message(outbuf,2,0,True);
2407 SIVALS(outbuf,smb_vwv0,res);
2409 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2410 fsp->fnum, (double)startpos, mode));
2412 return(outsize);
2415 /****************************************************************************
2416 reply to a flush
2417 ****************************************************************************/
2418 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2420 int outsize = set_message(outbuf,0,0,True);
2421 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2423 if (fsp) {
2424 CHECK_FSP(fsp,conn);
2425 CHECK_ERROR(fsp);
2428 if (!fsp) {
2429 file_sync_all(conn);
2430 } else {
2431 sync_file(conn,fsp);
2434 DEBUG(3,("flush\n"));
2435 return(outsize);
2439 /****************************************************************************
2440 reply to a exit
2441 ****************************************************************************/
2442 int reply_exit(connection_struct *conn,
2443 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2445 int outsize = set_message(outbuf,0,0,True);
2446 DEBUG(3,("exit\n"));
2448 return(outsize);
2452 /****************************************************************************
2453 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2454 ****************************************************************************/
2455 int reply_close(connection_struct *conn,
2456 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2458 int outsize = 0;
2459 time_t mtime;
2460 int32 eclass = 0, err = 0;
2461 files_struct *fsp = NULL;
2463 outsize = set_message(outbuf,0,0,True);
2465 /* If it's an IPC, pass off to the pipe handler. */
2466 if (IS_IPC(conn)) {
2467 return reply_pipe_close(conn, inbuf,outbuf);
2470 fsp = file_fsp(inbuf,smb_vwv0);
2473 * We can only use CHECK_FSP if we know it's not a directory.
2476 if(!fsp || !fsp->open || (fsp->conn != conn))
2477 return(ERROR(ERRDOS,ERRbadfid));
2479 if(HAS_CACHED_ERROR(fsp)) {
2480 eclass = fsp->wbmpx_ptr->wr_errclass;
2481 err = fsp->wbmpx_ptr->wr_error;
2484 if(fsp->is_directory) {
2486 * Special case - close NT SMB directory
2487 * handle.
2489 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2490 close_directory(fsp);
2491 } else {
2493 * Close ordinary file.
2497 * If there was a modify time outstanding,
2498 * try and set it here.
2500 if(fsp->pending_modtime)
2501 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2504 * Now take care of any time sent in the close.
2506 mtime = make_unix_date3(inbuf+smb_vwv1);
2508 /* try and set the date */
2509 set_filetime(conn, fsp->fsp_name,mtime);
2511 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2512 fsp->fd_ptr->fd, fsp->fnum,
2513 conn->num_files_open));
2515 close_file(fsp,True);
2518 /* We have a cached error */
2519 if(eclass || err)
2520 return(ERROR(eclass,err));
2522 return(outsize);
2526 /****************************************************************************
2527 reply to a writeclose (Core+ protocol)
2528 ****************************************************************************/
2529 int reply_writeclose(connection_struct *conn,
2530 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2532 size_t numtowrite;
2533 ssize_t nwritten = -1;
2534 int outsize = 0;
2535 SMB_OFF_T startpos;
2536 char *data;
2537 time_t mtime;
2538 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2540 CHECK_FSP(fsp,conn);
2541 CHECK_WRITE(fsp);
2542 CHECK_ERROR(fsp);
2544 numtowrite = SVAL(inbuf,smb_vwv1);
2545 startpos = IVAL(inbuf,smb_vwv2);
2546 mtime = make_unix_date3(inbuf+smb_vwv4);
2547 data = smb_buf(inbuf) + 1;
2549 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2550 return(ERROR(ERRDOS,ERRlock));
2552 if(seek_file(fsp,startpos) == -1)
2553 return(UNIXERROR(ERRDOS,ERRnoaccess));
2555 nwritten = write_file(fsp,data,numtowrite);
2557 set_filetime(conn, fsp->fsp_name,mtime);
2559 close_file(fsp,True);
2561 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2562 fsp->fnum, numtowrite, nwritten,
2563 conn->num_files_open));
2565 if (nwritten <= 0)
2566 return(UNIXERROR(ERRDOS,ERRnoaccess));
2568 outsize = set_message(outbuf,1,0,True);
2570 SSVAL(outbuf,smb_vwv0,nwritten);
2571 return(outsize);
2575 /****************************************************************************
2576 reply to a lock
2577 ****************************************************************************/
2578 int reply_lock(connection_struct *conn,
2579 char *inbuf,char *outbuf, int length, int dum_buffsize)
2581 int outsize = set_message(outbuf,0,0,True);
2582 SMB_OFF_T count,offset;
2583 int eclass;
2584 uint32 ecode;
2585 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2587 CHECK_FSP(fsp,conn);
2588 CHECK_ERROR(fsp);
2590 count = IVAL(inbuf,smb_vwv1);
2591 offset = IVAL(inbuf,smb_vwv3);
2593 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2594 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2596 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2597 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2599 * A blocking lock was requested. Package up
2600 * this smb into a queued request and push it
2601 * onto the blocking lock queue.
2603 if(push_blocking_lock_request(inbuf, length, -1, 0))
2604 return -1;
2606 return (ERROR(eclass,ecode));
2609 return(outsize);
2613 /****************************************************************************
2614 reply to a unlock
2615 ****************************************************************************/
2616 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2618 int outsize = set_message(outbuf,0,0,True);
2619 SMB_OFF_T count,offset;
2620 int eclass;
2621 uint32 ecode;
2622 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2624 CHECK_FSP(fsp,conn);
2625 CHECK_ERROR(fsp);
2627 count = IVAL(inbuf,smb_vwv1);
2628 offset = IVAL(inbuf,smb_vwv3);
2630 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2631 return (ERROR(eclass,ecode));
2633 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2634 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2636 return(outsize);
2640 /****************************************************************************
2641 reply to a tdis
2642 ****************************************************************************/
2643 int reply_tdis(connection_struct *conn,
2644 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2646 int outsize = set_message(outbuf,0,0,True);
2647 uint16 vuid;
2649 vuid = SVAL(inbuf,smb_uid);
2651 if (!conn) {
2652 DEBUG(4,("Invalid connection in tdis\n"));
2653 return(ERROR(ERRSRV,ERRinvnid));
2656 conn->used = False;
2658 close_cnum(conn,vuid);
2660 return outsize;
2665 /****************************************************************************
2666 reply to a echo
2667 ****************************************************************************/
2668 int reply_echo(connection_struct *conn,
2669 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2671 int smb_reverb = SVAL(inbuf,smb_vwv0);
2672 int seq_num;
2673 int data_len = smb_buflen(inbuf);
2674 int outsize = set_message(outbuf,1,data_len,True);
2676 /* copy any incoming data back out */
2677 if (data_len > 0)
2678 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2680 if (smb_reverb > 100) {
2681 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2682 smb_reverb = 100;
2685 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2686 SSVAL(outbuf,smb_vwv0,seq_num);
2688 smb_setlen(outbuf,outsize - 4);
2690 send_smb(Client,outbuf);
2693 DEBUG(3,("echo %d times\n", smb_reverb));
2695 return -1;
2699 /****************************************************************************
2700 reply to a printopen
2701 ****************************************************************************/
2702 int reply_printopen(connection_struct *conn,
2703 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2705 pstring fname;
2706 pstring fname2;
2707 int outsize = 0;
2708 files_struct *fsp;
2710 *fname = *fname2 = 0;
2712 if (!CAN_PRINT(conn))
2713 return(ERROR(ERRDOS,ERRnoaccess));
2716 pstring s;
2717 char *p;
2718 pstrcpy(s,smb_buf(inbuf)+1);
2719 p = s;
2720 while (*p) {
2721 if (!(isalnum((int)*p) || strchr("._-",*p)))
2722 *p = 'X';
2723 p++;
2726 if (strlen(s) > 10) s[10] = 0;
2728 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2731 fsp = file_new();
2732 if (!fsp)
2733 return(ERROR(ERRSRV,ERRnofids));
2735 pstrcpy(fname2,(char *)mktemp(fname));
2737 if (!check_name(fname2,conn)) {
2738 file_free(fsp);
2739 return(ERROR(ERRDOS,ERRnoaccess));
2742 /* Open for exclusive use, write only. */
2743 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2744 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2746 if (!fsp->open) {
2747 file_free(fsp);
2748 return(UNIXERROR(ERRDOS,ERRnoaccess));
2751 /* force it to be a print file */
2752 fsp->print_file = True;
2754 outsize = set_message(outbuf,1,0,True);
2755 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2757 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2758 fname2, fsp->fd_ptr->fd, fsp->fnum));
2760 return(outsize);
2764 /****************************************************************************
2765 reply to a printclose
2766 ****************************************************************************/
2767 int reply_printclose(connection_struct *conn,
2768 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2770 int outsize = set_message(outbuf,0,0,True);
2771 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2773 CHECK_FSP(fsp,conn);
2774 CHECK_ERROR(fsp);
2776 if (!CAN_PRINT(conn))
2777 return(ERROR(ERRDOS,ERRnoaccess));
2779 DEBUG(3,("printclose fd=%d fnum=%d\n",
2780 fsp->fd_ptr->fd,fsp->fnum));
2782 close_file(fsp,True);
2784 return(outsize);
2788 /****************************************************************************
2789 reply to a printqueue
2790 ****************************************************************************/
2791 int reply_printqueue(connection_struct *conn,
2792 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2794 int outsize = set_message(outbuf,2,3,True);
2795 int max_count = SVAL(inbuf,smb_vwv0);
2796 int start_index = SVAL(inbuf,smb_vwv1);
2798 /* we used to allow the client to get the cnum wrong, but that
2799 is really quite gross and only worked when there was only
2800 one printer - I think we should now only accept it if they
2801 get it right (tridge) */
2802 if (!CAN_PRINT(conn))
2803 return(ERROR(ERRDOS,ERRnoaccess));
2805 SSVAL(outbuf,smb_vwv0,0);
2806 SSVAL(outbuf,smb_vwv1,0);
2807 CVAL(smb_buf(outbuf),0) = 1;
2808 SSVAL(smb_buf(outbuf),1,0);
2810 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2811 start_index, max_count));
2814 print_queue_struct *queue = NULL;
2815 char *p = smb_buf(outbuf) + 3;
2816 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2817 int num_to_get = ABS(max_count);
2818 int first = (max_count>0?start_index:start_index+max_count+1);
2819 int i;
2821 if (first >= count)
2822 num_to_get = 0;
2823 else
2824 num_to_get = MIN(num_to_get,count-first);
2827 for (i=first;i<first+num_to_get;i++) {
2828 put_dos_date2(p,0,queue[i].time);
2829 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2830 SSVAL(p,5,printjob_encode(SNUM(conn),
2831 queue[i].job));
2832 SIVAL(p,7,queue[i].size);
2833 CVAL(p,11) = 0;
2834 StrnCpy(p+12,queue[i].user,16);
2835 p += 28;
2838 if (count > 0) {
2839 outsize = set_message(outbuf,2,28*count+3,False);
2840 SSVAL(outbuf,smb_vwv0,count);
2841 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2842 CVAL(smb_buf(outbuf),0) = 1;
2843 SSVAL(smb_buf(outbuf),1,28*count);
2846 if (queue) free(queue);
2848 DEBUG(3,("%d entries returned in queue\n",count));
2851 return(outsize);
2855 /****************************************************************************
2856 reply to a printwrite
2857 ****************************************************************************/
2858 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2860 int numtowrite;
2861 int outsize = set_message(outbuf,0,0,True);
2862 char *data;
2863 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2865 if (!CAN_PRINT(conn))
2866 return(ERROR(ERRDOS,ERRnoaccess));
2868 CHECK_FSP(fsp,conn);
2869 CHECK_WRITE(fsp);
2870 CHECK_ERROR(fsp);
2872 numtowrite = SVAL(smb_buf(inbuf),1);
2873 data = smb_buf(inbuf) + 3;
2875 if (write_file(fsp,data,numtowrite) != numtowrite)
2876 return(UNIXERROR(ERRDOS,ERRnoaccess));
2878 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2880 return(outsize);
2884 /****************************************************************************
2885 reply to a mkdir
2886 ****************************************************************************/
2887 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2889 pstring directory;
2890 int outsize,ret= -1;
2891 BOOL bad_path = False;
2893 pstrcpy(directory,smb_buf(inbuf) + 1);
2894 unix_convert(directory,conn,0,&bad_path,NULL);
2896 if (check_name(directory, conn))
2897 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2899 if (ret < 0)
2901 if((errno == ENOENT) && bad_path)
2903 unix_ERR_class = ERRDOS;
2904 unix_ERR_code = ERRbadpath;
2906 return(UNIXERROR(ERRDOS,ERRnoaccess));
2909 outsize = set_message(outbuf,0,0,True);
2911 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2913 return(outsize);
2916 /****************************************************************************
2917 Static function used by reply_rmdir to delete an entire directory
2918 tree recursively.
2919 ****************************************************************************/
2920 static BOOL recursive_rmdir(char *directory)
2922 char *dname = NULL;
2923 BOOL ret = False;
2924 void *dirptr = OpenDir(NULL, directory, False);
2926 if(dirptr == NULL)
2927 return True;
2929 while((dname = ReadDirName(dirptr)))
2931 pstring fullname;
2932 SMB_STRUCT_STAT st;
2934 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2935 continue;
2937 /* Construct the full name. */
2938 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2940 errno = ENOMEM;
2941 ret = True;
2942 break;
2944 pstrcpy(fullname, directory);
2945 pstrcat(fullname, "/");
2946 pstrcat(fullname, dname);
2948 if(dos_lstat(fullname, &st) != 0)
2950 ret = True;
2951 break;
2954 if(st.st_mode & S_IFDIR)
2956 if(recursive_rmdir(fullname)!=0)
2958 ret = True;
2959 break;
2961 if(dos_rmdir(fullname) != 0)
2963 ret = True;
2964 break;
2967 else if(dos_unlink(fullname) != 0)
2969 ret = True;
2970 break;
2973 CloseDir(dirptr);
2974 return ret;
2977 /****************************************************************************
2978 reply to a rmdir
2979 ****************************************************************************/
2980 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2982 pstring directory;
2983 int outsize = 0;
2984 BOOL ok = False;
2985 BOOL bad_path = False;
2987 pstrcpy(directory,smb_buf(inbuf) + 1);
2988 unix_convert(directory,conn, NULL,&bad_path,NULL);
2990 if (check_name(directory,conn))
2993 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2994 ok = (dos_rmdir(directory) == 0);
2995 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2997 /* Check to see if the only thing in this directory are
2998 vetoed files/directories. If so then delete them and
2999 retry. If we fail to delete any of them (and we *don't*
3000 do a recursive delete) then fail the rmdir. */
3001 BOOL all_veto_files = True;
3002 char *dname;
3003 void *dirptr = OpenDir(conn, directory, False);
3005 if(dirptr != NULL)
3007 int dirpos = TellDir(dirptr);
3008 while ((dname = ReadDirName(dirptr)))
3010 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3011 continue;
3012 if(!IS_VETO_PATH(conn, dname))
3014 all_veto_files = False;
3015 break;
3018 if(all_veto_files)
3020 SeekDir(dirptr,dirpos);
3021 while ((dname = ReadDirName(dirptr)))
3023 pstring fullname;
3024 SMB_STRUCT_STAT st;
3026 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3027 continue;
3029 /* Construct the full name. */
3030 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3032 errno = ENOMEM;
3033 break;
3035 pstrcpy(fullname, directory);
3036 pstrcat(fullname, "/");
3037 pstrcat(fullname, dname);
3039 if(dos_lstat(fullname, &st) != 0)
3040 break;
3041 if(st.st_mode & S_IFDIR)
3043 if(lp_recursive_veto_delete(SNUM(conn)))
3045 if(recursive_rmdir(fullname) != 0)
3046 break;
3048 if(dos_rmdir(fullname) != 0)
3049 break;
3051 else if(dos_unlink(fullname) != 0)
3052 break;
3054 CloseDir(dirptr);
3055 /* Retry the rmdir */
3056 ok = (dos_rmdir(directory) == 0);
3058 else
3059 CloseDir(dirptr);
3061 else
3062 errno = ENOTEMPTY;
3065 if (!ok)
3066 DEBUG(3,("couldn't remove directory %s : %s\n",
3067 directory,strerror(errno)));
3070 if (!ok)
3072 if((errno == ENOENT) && bad_path)
3074 unix_ERR_class = ERRDOS;
3075 unix_ERR_code = ERRbadpath;
3077 return(UNIXERROR(ERRDOS,ERRbadpath));
3080 outsize = set_message(outbuf,0,0,True);
3082 DEBUG( 3, ( "rmdir %s\n", directory ) );
3084 return(outsize);
3088 /*******************************************************************
3089 resolve wildcards in a filename rename
3090 ********************************************************************/
3091 static BOOL resolve_wildcards(char *name1,char *name2)
3093 fstring root1,root2;
3094 fstring ext1,ext2;
3095 char *p,*p2;
3097 name1 = strrchr(name1,'/');
3098 name2 = strrchr(name2,'/');
3100 if (!name1 || !name2) return(False);
3102 fstrcpy(root1,name1);
3103 fstrcpy(root2,name2);
3104 p = strrchr(root1,'.');
3105 if (p) {
3106 *p = 0;
3107 fstrcpy(ext1,p+1);
3108 } else {
3109 fstrcpy(ext1,"");
3111 p = strrchr(root2,'.');
3112 if (p) {
3113 *p = 0;
3114 fstrcpy(ext2,p+1);
3115 } else {
3116 fstrcpy(ext2,"");
3119 p = root1;
3120 p2 = root2;
3121 while (*p2) {
3122 if (*p2 == '?') {
3123 *p2 = *p;
3124 p2++;
3125 } else {
3126 p2++;
3128 if (*p) p++;
3131 p = ext1;
3132 p2 = ext2;
3133 while (*p2) {
3134 if (*p2 == '?') {
3135 *p2 = *p;
3136 p2++;
3137 } else {
3138 p2++;
3140 if (*p) p++;
3143 pstrcpy(name2,root2);
3144 if (ext2[0]) {
3145 pstrcat(name2,".");
3146 pstrcat(name2,ext2);
3149 return(True);
3152 /*******************************************************************
3153 check if a user is allowed to rename a file
3154 ********************************************************************/
3155 static BOOL can_rename(char *fname,connection_struct *conn)
3157 SMB_STRUCT_STAT sbuf;
3159 if (!CAN_WRITE(conn)) return(False);
3161 if (dos_lstat(fname,&sbuf) != 0) return(False);
3162 if (!check_file_sharing(conn,fname,True)) return(False);
3164 return(True);
3167 /****************************************************************************
3168 The guts of the rename command, split out so it may be called by the NT SMB
3169 code.
3170 ****************************************************************************/
3171 int rename_internals(connection_struct *conn,
3172 char *inbuf, char *outbuf, char *name,
3173 char *newname, BOOL replace_if_exists)
3175 pstring directory;
3176 pstring mask;
3177 pstring newname_last_component;
3178 char *p;
3179 BOOL has_wild;
3180 BOOL bad_path1 = False;
3181 BOOL bad_path2 = False;
3182 int count=0;
3183 int error = ERRnoaccess;
3184 BOOL exists=False;
3186 *directory = *mask = 0;
3188 unix_convert(name,conn,0,&bad_path1,NULL);
3189 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3192 * Split the old name into directory and last component
3193 * strings. Note that unix_convert may have stripped off a
3194 * leading ./ from both name and newname if the rename is
3195 * at the root of the share. We need to make sure either both
3196 * name and newname contain a / character or neither of them do
3197 * as this is checked in resolve_wildcards().
3200 p = strrchr(name,'/');
3201 if (!p) {
3202 pstrcpy(directory,".");
3203 pstrcpy(mask,name);
3204 } else {
3205 *p = 0;
3206 pstrcpy(directory,name);
3207 pstrcpy(mask,p+1);
3208 *p = '/'; /* Replace needed for exceptional test below. */
3211 if (is_mangled(mask))
3212 check_mangled_cache( mask );
3214 has_wild = strchr(mask,'*') || strchr(mask,'?');
3216 if (!has_wild) {
3218 * No wildcards - just process the one file.
3220 BOOL is_short_name = is_8_3(name, True);
3222 /* Add a terminating '/' to the directory name. */
3223 pstrcat(directory,"/");
3224 pstrcat(directory,mask);
3226 /* Ensure newname contains a '/' also */
3227 if(strrchr(newname,'/') == 0) {
3228 pstring tmpstr;
3230 pstrcpy(tmpstr, "./");
3231 pstrcat(tmpstr, newname);
3232 pstrcpy(newname, tmpstr);
3235 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3236 case_sensitive, case_preserve, short_case_preserve, directory,
3237 newname, newname_last_component, is_short_name));
3240 * Check for special case with case preserving and not
3241 * case sensitive, if directory and newname are identical,
3242 * and the old last component differs from the original
3243 * last component only by case, then we should allow
3244 * the rename (user is trying to change the case of the
3245 * filename).
3247 if((case_sensitive == False) &&
3248 (((case_preserve == True) &&
3249 (is_short_name == False)) ||
3250 ((short_case_preserve == True) &&
3251 (is_short_name == True))) &&
3252 strcsequal(directory, newname)) {
3253 pstring newname_modified_last_component;
3256 * Get the last component of the modified name.
3257 * Note that we guarantee that newname contains a '/'
3258 * character above.
3260 p = strrchr(newname,'/');
3261 pstrcpy(newname_modified_last_component,p+1);
3263 if(strcsequal(newname_modified_last_component,
3264 newname_last_component) == False) {
3266 * Replace the modified last component with
3267 * the original.
3269 pstrcpy(p+1, newname_last_component);
3273 if(replace_if_exists) {
3275 * NT SMB specific flag - rename can overwrite
3276 * file with the same name so don't check for
3277 * dos_file_exist().
3279 if(resolve_wildcards(directory,newname) &&
3280 can_rename(directory,conn) &&
3281 !dos_rename(directory,newname))
3282 count++;
3283 } else {
3284 if (resolve_wildcards(directory,newname) &&
3285 can_rename(directory,conn) &&
3286 !dos_file_exist(newname,NULL) &&
3287 !dos_rename(directory,newname))
3288 count++;
3291 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3292 directory,newname));
3294 if (!count) exists = dos_file_exist(directory,NULL);
3295 if (!count && exists && dos_file_exist(newname,NULL)) {
3296 exists = True;
3297 error = ERRrename;
3299 } else {
3301 * Wildcards - process each file that matches.
3303 void *dirptr = NULL;
3304 char *dname;
3305 pstring destname;
3307 if (check_name(directory,conn))
3308 dirptr = OpenDir(conn, directory, True);
3310 if (dirptr) {
3311 error = ERRbadfile;
3313 if (strequal(mask,"????????.???"))
3314 pstrcpy(mask,"*");
3316 while ((dname = ReadDirName(dirptr))) {
3317 pstring fname;
3318 pstrcpy(fname,dname);
3320 if(!mask_match(fname, mask, case_sensitive, False))
3321 continue;
3323 error = ERRnoaccess;
3324 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3325 if (!can_rename(fname,conn)) {
3326 DEBUG(6,("rename %s refused\n", fname));
3327 continue;
3329 pstrcpy(destname,newname);
3331 if (!resolve_wildcards(fname,destname)) {
3332 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3333 continue;
3336 if (!replace_if_exists && dos_file_exist(destname,NULL)) {
3337 DEBUG(6,("dos_file_exist %s\n", destname));
3338 error = 183;
3339 continue;
3342 if (!dos_rename(fname,destname))
3343 count++;
3344 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3346 CloseDir(dirptr);
3350 if (count == 0) {
3351 if (exists)
3352 return(ERROR(ERRDOS,error));
3353 else {
3354 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3355 unix_ERR_class = ERRDOS;
3356 unix_ERR_code = ERRbadpath;
3358 return(UNIXERROR(ERRDOS,error));
3362 return 0;
3365 /****************************************************************************
3366 Reply to a mv.
3367 ****************************************************************************/
3369 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3371 int outsize = 0;
3372 pstring name;
3373 pstring newname;
3375 pstrcpy(name,smb_buf(inbuf) + 1);
3376 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3378 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3380 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3381 if(outsize == 0)
3382 outsize = set_message(outbuf,0,0,True);
3384 return(outsize);
3387 /*******************************************************************
3388 copy a file as part of a reply_copy
3389 ******************************************************************/
3391 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3392 int count,BOOL target_is_directory)
3394 int Access,action;
3395 SMB_STRUCT_STAT st;
3396 int ret=-1;
3397 files_struct *fsp1,*fsp2;
3398 pstring dest;
3400 pstrcpy(dest,dest1);
3401 if (target_is_directory) {
3402 char *p = strrchr(src,'/');
3403 if (p)
3404 p++;
3405 else
3406 p = src;
3407 pstrcat(dest,"/");
3408 pstrcat(dest,p);
3411 if (!dos_file_exist(src,&st))
3412 return(False);
3414 fsp1 = file_new();
3415 if (!fsp1)
3416 return(False);
3418 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3419 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3421 if (!fsp1->open) {
3422 file_free(fsp1);
3423 return(False);
3426 if (!target_is_directory && count)
3427 ofun = 1;
3429 fsp2 = file_new();
3430 if (!fsp2) {
3431 close_file(fsp1,False);
3432 return(False);
3434 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3435 ofun,st.st_mode,0,&Access,&action);
3437 if (!fsp2->open) {
3438 close_file(fsp1,False);
3439 file_free(fsp2);
3440 return(False);
3443 if ((ofun&3) == 1) {
3444 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3445 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3446 strerror(errno) ));
3448 * Stop the copy from occurring.
3450 ret = -1;
3451 st.st_size = 0;
3455 if (st.st_size)
3456 ret = transfer_file(fsp1->fd_ptr->fd,
3457 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3459 close_file(fsp1,False);
3460 close_file(fsp2,False);
3462 return(ret == st.st_size);
3467 /****************************************************************************
3468 reply to a file copy.
3469 ****************************************************************************/
3470 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3472 int outsize = 0;
3473 pstring name;
3474 pstring directory;
3475 pstring mask,newname;
3476 char *p;
3477 int count=0;
3478 int error = ERRnoaccess;
3479 BOOL has_wild;
3480 BOOL exists=False;
3481 int tid2 = SVAL(inbuf,smb_vwv0);
3482 int ofun = SVAL(inbuf,smb_vwv1);
3483 int flags = SVAL(inbuf,smb_vwv2);
3484 BOOL target_is_directory=False;
3485 BOOL bad_path1 = False;
3486 BOOL bad_path2 = False;
3488 *directory = *mask = 0;
3490 pstrcpy(name,smb_buf(inbuf));
3491 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3493 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3495 if (tid2 != conn->cnum) {
3496 /* can't currently handle inter share copies XXXX */
3497 DEBUG(3,("Rejecting inter-share copy\n"));
3498 return(ERROR(ERRSRV,ERRinvdevice));
3501 unix_convert(name,conn,0,&bad_path1,NULL);
3502 unix_convert(newname,conn,0,&bad_path2,NULL);
3504 target_is_directory = dos_directory_exist(newname,NULL);
3506 if ((flags&1) && target_is_directory) {
3507 return(ERROR(ERRDOS,ERRbadfile));
3510 if ((flags&2) && !target_is_directory) {
3511 return(ERROR(ERRDOS,ERRbadpath));
3514 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3515 /* wants a tree copy! XXXX */
3516 DEBUG(3,("Rejecting tree copy\n"));
3517 return(ERROR(ERRSRV,ERRerror));
3520 p = strrchr(name,'/');
3521 if (!p) {
3522 pstrcpy(directory,"./");
3523 pstrcpy(mask,name);
3524 } else {
3525 *p = 0;
3526 pstrcpy(directory,name);
3527 pstrcpy(mask,p+1);
3530 if (is_mangled(mask))
3531 check_mangled_cache( mask );
3533 has_wild = strchr(mask,'*') || strchr(mask,'?');
3535 if (!has_wild) {
3536 pstrcat(directory,"/");
3537 pstrcat(directory,mask);
3538 if (resolve_wildcards(directory,newname) &&
3539 copy_file(directory,newname,conn,ofun,
3540 count,target_is_directory)) count++;
3541 if (!count) exists = dos_file_exist(directory,NULL);
3542 } else {
3543 void *dirptr = NULL;
3544 char *dname;
3545 pstring destname;
3547 if (check_name(directory,conn))
3548 dirptr = OpenDir(conn, directory, True);
3550 if (dirptr)
3552 error = ERRbadfile;
3554 if (strequal(mask,"????????.???"))
3555 pstrcpy(mask,"*");
3557 while ((dname = ReadDirName(dirptr)))
3559 pstring fname;
3560 pstrcpy(fname,dname);
3562 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3564 error = ERRnoaccess;
3565 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3566 pstrcpy(destname,newname);
3567 if (resolve_wildcards(fname,destname) &&
3568 copy_file(directory,newname,conn,ofun,
3569 count,target_is_directory)) count++;
3570 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3572 CloseDir(dirptr);
3576 if (count == 0) {
3577 if (exists)
3578 return(ERROR(ERRDOS,error));
3579 else
3581 if((errno == ENOENT) && (bad_path1 || bad_path2))
3583 unix_ERR_class = ERRDOS;
3584 unix_ERR_code = ERRbadpath;
3586 return(UNIXERROR(ERRDOS,error));
3590 outsize = set_message(outbuf,1,0,True);
3591 SSVAL(outbuf,smb_vwv0,count);
3593 return(outsize);
3596 /****************************************************************************
3597 reply to a setdir
3598 ****************************************************************************/
3599 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3601 int snum;
3602 int outsize = 0;
3603 BOOL ok = False;
3604 pstring newdir;
3606 snum = SNUM(conn);
3607 if (!CAN_SETDIR(snum))
3608 return(ERROR(ERRDOS,ERRnoaccess));
3610 pstrcpy(newdir,smb_buf(inbuf) + 1);
3611 strlower(newdir);
3613 if (strlen(newdir) == 0) {
3614 ok = True;
3615 } else {
3616 ok = dos_directory_exist(newdir,NULL);
3617 if (ok) {
3618 string_set(&conn->connectpath,newdir);
3622 if (!ok)
3623 return(ERROR(ERRDOS,ERRbadpath));
3625 outsize = set_message(outbuf,0,0,True);
3626 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3628 DEBUG(3,("setdir %s\n", newdir));
3630 return(outsize);
3633 /****************************************************************************
3634 reply to a lockingX request
3635 ****************************************************************************/
3636 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3638 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3639 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3640 #if 0
3641 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3642 #endif
3643 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3644 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3645 SMB_OFF_T count = 0, offset = 0;
3646 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3647 int i;
3648 char *data;
3649 uint32 ecode=0, dummy2;
3650 int eclass=0, dummy1;
3651 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3652 CHECK_FSP(fsp,conn);
3653 CHECK_ERROR(fsp);
3655 data = smb_buf(inbuf);
3657 /* Check if this is an oplock break on a file
3658 we have granted an oplock on.
3660 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3662 int token;
3663 SMB_DEV_T dev = fsp->fd_ptr->dev;
3664 SMB_INO_T inode = fsp->fd_ptr->inode;
3666 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3667 fsp->fnum));
3669 * Make sure we have granted an oplock on this file.
3671 if(!fsp->granted_oplock)
3673 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3674 no oplock granted on this file.\n", fsp->fnum));
3675 return ERROR(ERRDOS,ERRlock);
3678 /* Remove the oplock flag from the sharemode. */
3679 lock_share_entry(fsp->conn, dev, inode, &token);
3680 if(remove_share_oplock(token, fsp)==False) {
3682 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3683 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3685 unlock_share_entry(fsp->conn, dev, inode, token);
3686 } else {
3687 unlock_share_entry(fsp->conn, dev, inode, token);
3689 /* Clear the granted flag and return. */
3690 fsp->granted_oplock = False;
3693 /* if this is a pure oplock break request then don't send a reply */
3694 if (num_locks == 0 && num_ulocks == 0)
3696 /* Sanity check - ensure a pure oplock break is not a
3697 chained request. */
3698 if(CVAL(inbuf,smb_vwv0) != 0xff)
3699 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3700 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3701 return -1;
3705 /* Data now points at the beginning of the list
3706 of smb_unlkrng structs */
3707 for(i = 0; i < (int)num_ulocks; i++) {
3708 if(!large_file_format) {
3709 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3710 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3712 #ifdef LARGE_SMB_OFF_T
3713 else {
3714 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3715 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3716 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3717 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3719 #endif /* LARGE_SMB_OFF_T */
3721 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3722 (double)offset, (double)count, fsp->fsp_name ));
3724 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3725 return ERROR(eclass,ecode);
3728 /* Setup the timeout in seconds. */
3729 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3731 /* Now do any requested locks */
3732 data += ((large_file_format ? 20 : 10)*num_ulocks);
3734 /* Data now points at the beginning of the list
3735 of smb_lkrng structs */
3737 for(i = 0; i < (int)num_locks; i++) {
3738 if(!large_file_format) {
3739 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3740 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3742 #ifdef LARGE_SMB_OFF_T
3743 else {
3744 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3745 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3746 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3747 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3749 #endif /* LARGE_SMB_OFF_T */
3751 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3752 (double)offset, (double)count, fsp->fsp_name ));
3754 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3755 &eclass, &ecode)) {
3756 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3758 * A blocking lock was requested. Package up
3759 * this smb into a queued request and push it
3760 * onto the blocking lock queue.
3762 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3763 return -1;
3765 break;
3769 /* If any of the above locks failed, then we must unlock
3770 all of the previous locks (X/Open spec). */
3771 if(i != num_locks && num_locks != 0) {
3772 for(; i >= 0; i--) {
3773 if(!large_file_format) {
3774 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3775 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3777 #ifdef LARGE_SMB_OFF_T
3778 else {
3779 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3780 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3781 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3782 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3784 #endif /* LARGE_SMB_OFF_T */
3786 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3788 return ERROR(eclass,ecode);
3791 set_message(outbuf,2,0,True);
3793 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3794 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3796 return chain_reply(inbuf,outbuf,length,bufsize);
3800 /****************************************************************************
3801 reply to a SMBreadbmpx (read block multiplex) request
3802 ****************************************************************************/
3803 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3805 ssize_t nread = -1;
3806 ssize_t total_read;
3807 char *data;
3808 SMB_OFF_T startpos;
3809 int outsize;
3810 size_t maxcount;
3811 int max_per_packet;
3812 size_t tcount;
3813 int pad;
3814 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3816 /* this function doesn't seem to work - disable by default */
3817 if (!lp_readbmpx())
3818 return(ERROR(ERRSRV,ERRuseSTD));
3820 outsize = set_message(outbuf,8,0,True);
3822 CHECK_FSP(fsp,conn);
3823 CHECK_READ(fsp);
3824 CHECK_ERROR(fsp);
3826 startpos = IVAL(inbuf,smb_vwv1);
3827 maxcount = SVAL(inbuf,smb_vwv3);
3829 data = smb_buf(outbuf);
3830 pad = ((long)data)%4;
3831 if (pad) pad = 4 - pad;
3832 data += pad;
3834 max_per_packet = bufsize-(outsize+pad);
3835 tcount = maxcount;
3836 total_read = 0;
3838 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3839 return(ERROR(ERRDOS,ERRlock));
3843 size_t N = MIN(max_per_packet,tcount-total_read);
3845 nread = read_file(fsp,data,startpos,N);
3847 if (nread <= 0) nread = 0;
3849 if (nread < (ssize_t)N)
3850 tcount = total_read + nread;
3852 set_message(outbuf,8,nread,False);
3853 SIVAL(outbuf,smb_vwv0,startpos);
3854 SSVAL(outbuf,smb_vwv2,tcount);
3855 SSVAL(outbuf,smb_vwv6,nread);
3856 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3858 send_smb(Client,outbuf);
3860 total_read += nread;
3861 startpos += nread;
3863 while (total_read < (ssize_t)tcount);
3865 return(-1);
3868 /****************************************************************************
3869 reply to a SMBwritebmpx (write block multiplex primary) request
3870 ****************************************************************************/
3871 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3873 size_t numtowrite;
3874 ssize_t nwritten = -1;
3875 int outsize = 0;
3876 SMB_OFF_T startpos;
3877 size_t tcount;
3878 BOOL write_through;
3879 int smb_doff;
3880 char *data;
3881 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3883 CHECK_FSP(fsp,conn);
3884 CHECK_WRITE(fsp);
3885 CHECK_ERROR(fsp);
3887 tcount = SVAL(inbuf,smb_vwv1);
3888 startpos = IVAL(inbuf,smb_vwv3);
3889 write_through = BITSETW(inbuf+smb_vwv7,0);
3890 numtowrite = SVAL(inbuf,smb_vwv10);
3891 smb_doff = SVAL(inbuf,smb_vwv11);
3893 data = smb_base(inbuf) + smb_doff;
3895 /* If this fails we need to send an SMBwriteC response,
3896 not an SMBwritebmpx - set this up now so we don't forget */
3897 CVAL(outbuf,smb_com) = SMBwritec;
3899 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3900 return(ERROR(ERRDOS,ERRlock));
3902 if(seek_file(fsp,startpos) == -1)
3903 return(UNIXERROR(ERRDOS,ERRnoaccess));
3905 nwritten = write_file(fsp,data,numtowrite);
3907 if(lp_syncalways(SNUM(conn)) || write_through)
3908 sync_file(conn,fsp);
3910 if(nwritten < (ssize_t)numtowrite)
3911 return(UNIXERROR(ERRHRD,ERRdiskfull));
3913 /* If the maximum to be written to this file
3914 is greater than what we just wrote then set
3915 up a secondary struct to be attached to this
3916 fd, we will use this to cache error messages etc. */
3917 if((ssize_t)tcount > nwritten)
3919 write_bmpx_struct *wbms;
3920 if(fsp->wbmpx_ptr != NULL)
3921 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3922 else
3923 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3924 if(!wbms)
3926 DEBUG(0,("Out of memory in reply_readmpx\n"));
3927 return(ERROR(ERRSRV,ERRnoresource));
3929 wbms->wr_mode = write_through;
3930 wbms->wr_discard = False; /* No errors yet */
3931 wbms->wr_total_written = nwritten;
3932 wbms->wr_errclass = 0;
3933 wbms->wr_error = 0;
3934 fsp->wbmpx_ptr = wbms;
3937 /* We are returning successfully, set the message type back to
3938 SMBwritebmpx */
3939 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3941 outsize = set_message(outbuf,1,0,True);
3943 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3945 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3946 fsp->fnum, numtowrite, nwritten ) );
3948 if (write_through && tcount==nwritten) {
3949 /* we need to send both a primary and a secondary response */
3950 smb_setlen(outbuf,outsize - 4);
3951 send_smb(Client,outbuf);
3953 /* now the secondary */
3954 outsize = set_message(outbuf,1,0,True);
3955 CVAL(outbuf,smb_com) = SMBwritec;
3956 SSVAL(outbuf,smb_vwv0,nwritten);
3959 return(outsize);
3963 /****************************************************************************
3964 reply to a SMBwritebs (write block multiplex secondary) request
3965 ****************************************************************************/
3966 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3968 size_t numtowrite;
3969 ssize_t nwritten = -1;
3970 int outsize = 0;
3971 SMB_OFF_T startpos;
3972 size_t tcount;
3973 BOOL write_through;
3974 int smb_doff;
3975 char *data;
3976 write_bmpx_struct *wbms;
3977 BOOL send_response = False;
3978 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3980 CHECK_FSP(fsp,conn);
3981 CHECK_WRITE(fsp);
3983 tcount = SVAL(inbuf,smb_vwv1);
3984 startpos = IVAL(inbuf,smb_vwv2);
3985 numtowrite = SVAL(inbuf,smb_vwv6);
3986 smb_doff = SVAL(inbuf,smb_vwv7);
3988 data = smb_base(inbuf) + smb_doff;
3990 /* We need to send an SMBwriteC response, not an SMBwritebs */
3991 CVAL(outbuf,smb_com) = SMBwritec;
3993 /* This fd should have an auxiliary struct attached,
3994 check that it does */
3995 wbms = fsp->wbmpx_ptr;
3996 if(!wbms) return(-1);
3998 /* If write through is set we can return errors, else we must
3999 cache them */
4000 write_through = wbms->wr_mode;
4002 /* Check for an earlier error */
4003 if(wbms->wr_discard)
4004 return -1; /* Just discard the packet */
4006 if(seek_file(fsp,startpos) == -1)
4008 if(write_through)
4010 /* We are returning an error - we can delete the aux struct */
4011 if (wbms) free((char *)wbms);
4012 fsp->wbmpx_ptr = NULL;
4013 return(UNIXERROR(ERRDOS,ERRnoaccess));
4015 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4018 nwritten = write_file(fsp,data,numtowrite);
4020 if(lp_syncalways(SNUM(conn)) || write_through)
4021 sync_file(conn,fsp);
4023 if (nwritten < (ssize_t)numtowrite)
4025 if(write_through)
4027 /* We are returning an error - we can delete the aux struct */
4028 if (wbms) free((char *)wbms);
4029 fsp->wbmpx_ptr = NULL;
4030 return(ERROR(ERRHRD,ERRdiskfull));
4032 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4035 /* Increment the total written, if this matches tcount
4036 we can discard the auxiliary struct (hurrah !) and return a writeC */
4037 wbms->wr_total_written += nwritten;
4038 if(wbms->wr_total_written >= tcount)
4040 if (write_through)
4042 outsize = set_message(outbuf,1,0,True);
4043 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4044 send_response = True;
4047 free((char *)wbms);
4048 fsp->wbmpx_ptr = NULL;
4051 if(send_response)
4052 return(outsize);
4054 return(-1);
4058 /****************************************************************************
4059 reply to a SMBsetattrE
4060 ****************************************************************************/
4061 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4063 struct utimbuf unix_times;
4064 int outsize = 0;
4065 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4067 outsize = set_message(outbuf,0,0,True);
4069 CHECK_FSP(fsp,conn);
4070 CHECK_ERROR(fsp);
4072 /* Convert the DOS times into unix times. Ignore create
4073 time as UNIX can't set this.
4075 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4076 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4079 * Patch from Ray Frush <frush@engr.colostate.edu>
4080 * Sometimes times are sent as zero - ignore them.
4083 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4085 /* Ignore request */
4086 if( DEBUGLVL( 3 ) )
4088 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4089 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4091 return(outsize);
4093 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4095 /* set modify time = to access time if modify time was 0 */
4096 unix_times.modtime = unix_times.actime;
4099 /* Set the date on this file */
4100 if(file_utime(conn, fsp->fsp_name, &unix_times))
4101 return(ERROR(ERRDOS,ERRnoaccess));
4103 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4104 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4106 return(outsize);
4110 /****************************************************************************
4111 reply to a SMBgetattrE
4112 ****************************************************************************/
4113 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4115 SMB_STRUCT_STAT sbuf;
4116 int outsize = 0;
4117 int mode;
4118 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4120 outsize = set_message(outbuf,11,0,True);
4122 CHECK_FSP(fsp,conn);
4123 CHECK_ERROR(fsp);
4125 /* Do an fstat on this file */
4126 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4127 return(UNIXERROR(ERRDOS,ERRnoaccess));
4129 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4131 /* Convert the times into dos times. Set create
4132 date to be last modify date as UNIX doesn't save
4133 this */
4134 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4135 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4136 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4137 if (mode & aDIR)
4139 SIVAL(outbuf,smb_vwv6,0);
4140 SIVAL(outbuf,smb_vwv8,0);
4142 else
4144 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4145 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4147 SSVAL(outbuf,smb_vwv10, mode);
4149 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4151 return(outsize);