Makefile.in configure configure.in include/proto.h smbd/noquotas.c smbd/quotas.c:
[Samba/gebeck_regimport.git] / source / smbd / reply.c
blob67c2abb9b54cdc7ef0922f2549a6d103e6fcc24d
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 (GUEST_SESSSETUP == 0)
705 return(ERROR(ERRSRV,ERRbadpw));
706 #endif
707 #if (GUEST_SESSSETUP == 1)
708 if (Get_Pwnam(user,True))
709 return(ERROR(ERRSRV,ERRbadpw));
710 #endif
712 if (*smb_apasswd || !Get_Pwnam(user,True))
713 pstrcpy(user,lp_guestaccount(-1));
714 DEBUG(3,("Registered username %s for guest access\n",user));
715 guest = True;
719 if (!Get_Pwnam(user,True)) {
720 DEBUG(3,("No such user %s - using guest account\n",user));
721 pstrcpy(user,lp_guestaccount(-1));
722 guest = True;
725 if (!strequal(user,lp_guestaccount(-1)) &&
726 lp_servicenumber(user) < 0)
728 int homes = lp_servicenumber(HOMES_NAME);
729 char *home = get_home_dir(user);
730 if (homes >= 0 && home)
731 lp_add_home(user,homes,home);
735 /* it's ok - setup a reply */
736 if (Protocol < PROTOCOL_NT1) {
737 set_message(outbuf,3,0,True);
738 } else {
739 char *p;
740 set_message(outbuf,3,3,True);
741 p = smb_buf(outbuf);
742 pstrcpy(p,"Unix"); p = skip_string(p,1);
743 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
744 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
745 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
746 /* perhaps grab OS version here?? */
749 /* Set the correct uid in the outgoing and incoming packets
750 We will use this on future requests to determine which
751 user we should become.
754 struct passwd *pw = Get_Pwnam(user,False);
755 if (!pw) {
756 DEBUG(1,("Username %s is invalid on this system\n",user));
757 return(ERROR(ERRSRV,ERRbadpw));
759 gid = pw->pw_gid;
760 uid = pw->pw_uid;
763 if (guest)
764 SSVAL(outbuf,smb_vwv2,1);
766 /* register the name and uid as being validated, so further connections
767 to a uid can get through without a password, on the same VC */
768 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
770 SSVAL(outbuf,smb_uid,sess_vuid);
771 SSVAL(inbuf,smb_uid,sess_vuid);
773 if (!done_sesssetup)
774 max_send = MIN(max_send,smb_bufsize);
776 DEBUG(6,("Client requested max send size of %d\n", max_send));
778 done_sesssetup = True;
780 return chain_reply(inbuf,outbuf,length,bufsize);
784 /****************************************************************************
785 reply to a chkpth
786 ****************************************************************************/
787 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
789 int outsize = 0;
790 int mode;
791 pstring name;
792 BOOL ok = False;
793 BOOL bad_path = False;
794 SMB_STRUCT_STAT st;
796 pstrcpy(name,smb_buf(inbuf) + 1);
797 unix_convert(name,conn,0,&bad_path,&st);
799 mode = SVAL(inbuf,smb_vwv0);
801 if (check_name(name,conn)) {
802 if(VALID_STAT(st))
803 ok = S_ISDIR(st.st_mode);
804 else
805 ok = directory_exist(name,NULL);
808 if (!ok)
810 /* We special case this - as when a Windows machine
811 is parsing a path is steps through the components
812 one at a time - if a component fails it expects
813 ERRbadpath, not ERRbadfile.
815 if(errno == ENOENT)
817 unix_ERR_class = ERRDOS;
818 unix_ERR_code = ERRbadpath;
821 #if 0
822 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
823 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
824 (get_remote_arch() == RA_WINNT))
826 unix_ERR_class = ERRDOS;
827 unix_ERR_code = ERRbaddirectory;
829 #endif
831 return(UNIXERROR(ERRDOS,ERRbadpath));
834 outsize = set_message(outbuf,0,0,True);
836 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
838 return(outsize);
842 /****************************************************************************
843 reply to a getatr
844 ****************************************************************************/
845 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
847 pstring fname;
848 int outsize = 0;
849 SMB_STRUCT_STAT sbuf;
850 BOOL ok = False;
851 int mode=0;
852 SMB_OFF_T size=0;
853 time_t mtime=0;
854 BOOL bad_path = False;
856 pstrcpy(fname,smb_buf(inbuf) + 1);
858 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
859 under WfWg - weird! */
860 if (! (*fname))
862 mode = aHIDDEN | aDIR;
863 if (!CAN_WRITE(conn)) mode |= aRONLY;
864 size = 0;
865 mtime = 0;
866 ok = True;
868 else
870 unix_convert(fname,conn,0,&bad_path,&sbuf);
871 if (check_name(fname,conn))
873 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
875 mode = dos_mode(conn,fname,&sbuf);
876 size = sbuf.st_size;
877 mtime = sbuf.st_mtime;
878 if (mode & aDIR)
879 size = 0;
880 ok = True;
882 else
883 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
887 if (!ok)
889 if((errno == ENOENT) && bad_path)
891 unix_ERR_class = ERRDOS;
892 unix_ERR_code = ERRbadpath;
895 return(UNIXERROR(ERRDOS,ERRbadfile));
898 outsize = set_message(outbuf,10,0,True);
900 SSVAL(outbuf,smb_vwv0,mode);
901 if(lp_dos_filetime_resolution(SNUM(conn)) )
902 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
903 else
904 put_dos_date3(outbuf,smb_vwv1,mtime);
905 SIVAL(outbuf,smb_vwv3,(uint32)size);
907 if (Protocol >= PROTOCOL_NT1) {
908 char *p = strrchr(fname,'/');
909 uint16 flg2 = SVAL(outbuf,smb_flg2);
910 if (!p) p = fname;
911 if (!is_8_3(fname, True))
912 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
915 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
917 return(outsize);
921 /****************************************************************************
922 reply to a setatr
923 ****************************************************************************/
924 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
926 pstring fname;
927 int outsize = 0;
928 BOOL ok=False;
929 int mode;
930 time_t mtime;
931 SMB_STRUCT_STAT st;
932 BOOL bad_path = False;
934 pstrcpy(fname,smb_buf(inbuf) + 1);
935 unix_convert(fname,conn,0,&bad_path,&st);
937 mode = SVAL(inbuf,smb_vwv0);
938 mtime = make_unix_date3(inbuf+smb_vwv1);
940 if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL))
941 mode |= aDIR;
942 if (check_name(fname,conn))
943 ok = (file_chmod(conn,fname,mode,NULL) == 0);
944 if (ok)
945 ok = set_filetime(conn,fname,mtime);
947 if (!ok)
949 if((errno == ENOENT) && bad_path)
951 unix_ERR_class = ERRDOS;
952 unix_ERR_code = ERRbadpath;
955 return(UNIXERROR(ERRDOS,ERRnoaccess));
958 outsize = set_message(outbuf,0,0,True);
960 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
962 return(outsize);
966 /****************************************************************************
967 reply to a dskattr
968 ****************************************************************************/
969 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
971 int outsize = 0;
972 SMB_BIG_UINT dfree,dsize,bsize;
974 sys_disk_free(".",&bsize,&dfree,&dsize);
976 outsize = set_message(outbuf,5,0,True);
978 SSVAL(outbuf,smb_vwv0,dsize);
979 SSVAL(outbuf,smb_vwv1,bsize/512);
980 SSVAL(outbuf,smb_vwv2,512);
981 SSVAL(outbuf,smb_vwv3,dfree);
983 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
985 return(outsize);
989 /****************************************************************************
990 reply to a search
991 Can be called from SMBsearch, SMBffirst or SMBfunique.
992 ****************************************************************************/
993 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
995 pstring mask;
996 pstring directory;
997 pstring fname;
998 SMB_OFF_T size;
999 int mode;
1000 time_t date;
1001 int dirtype;
1002 int outsize = 0;
1003 int numentries = 0;
1004 BOOL finished = False;
1005 int maxentries;
1006 int i;
1007 char *p;
1008 BOOL ok = False;
1009 int status_len;
1010 char *path;
1011 char status[21];
1012 int dptr_num= -1;
1013 BOOL check_descend = False;
1014 BOOL expect_close = False;
1015 BOOL can_open = True;
1016 BOOL bad_path = False;
1018 *mask = *directory = *fname = 0;
1020 /* If we were called as SMBffirst then we must expect close. */
1021 if(CVAL(inbuf,smb_com) == SMBffirst)
1022 expect_close = True;
1024 outsize = set_message(outbuf,1,3,True);
1025 maxentries = SVAL(inbuf,smb_vwv0);
1026 dirtype = SVAL(inbuf,smb_vwv1);
1027 path = smb_buf(inbuf) + 1;
1028 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1031 /* dirtype &= ~aDIR; */
1033 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1036 if (status_len == 0)
1038 pstring dir2;
1040 pstrcpy(directory,smb_buf(inbuf)+1);
1041 pstrcpy(dir2,smb_buf(inbuf)+1);
1042 unix_convert(directory,conn,0,&bad_path,NULL);
1043 unix_format(dir2);
1045 if (!check_name(directory,conn))
1046 can_open = False;
1048 p = strrchr(dir2,'/');
1049 if (p == NULL)
1051 pstrcpy(mask,dir2);
1052 *dir2 = 0;
1054 else
1056 *p = 0;
1057 pstrcpy(mask,p+1);
1060 p = strrchr(directory,'/');
1061 if (!p)
1062 *directory = 0;
1063 else
1064 *p = 0;
1066 if (strlen(directory) == 0)
1067 pstrcpy(directory,"./");
1068 bzero(status,21);
1069 CVAL(status,0) = dirtype;
1071 else
1073 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1074 memcpy(mask,status+1,11);
1075 mask[11] = 0;
1076 dirtype = CVAL(status,0) & 0x1F;
1077 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1078 if (!conn->dirptr)
1079 goto SearchEmpty;
1080 string_set(&conn->dirpath,dptr_path(dptr_num));
1081 if (!case_sensitive)
1082 strnorm(mask);
1085 /* turn strings of spaces into a . */
1087 trim_string(mask,NULL," ");
1088 if ((p = strrchr(mask,' ')))
1090 fstring ext;
1091 fstrcpy(ext,p+1);
1092 *p = 0;
1093 trim_string(mask,NULL," ");
1094 pstrcat(mask,".");
1095 pstrcat(mask,ext);
1099 /* Convert the formatted mask. (This code lives in trans2.c) */
1100 mask_convert(mask);
1103 int skip;
1104 p = mask;
1105 while(*p)
1107 if((skip = skip_multibyte_char( *p )) != 0 )
1109 p += skip;
1111 else
1113 if (*p != '?' && *p != '*' && !isdoschar(*p))
1115 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1116 *p = '?';
1118 p++;
1123 if (!strchr(mask,'.') && strlen(mask)>8)
1125 fstring tmp;
1126 fstrcpy(tmp,&mask[8]);
1127 mask[8] = '.';
1128 mask[9] = 0;
1129 pstrcat(mask,tmp);
1132 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1134 if (can_open)
1136 p = smb_buf(outbuf) + 3;
1138 ok = True;
1140 if (status_len == 0)
1142 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1143 if (dptr_num < 0)
1145 if(dptr_num == -2)
1147 if((errno == ENOENT) && bad_path)
1149 unix_ERR_class = ERRDOS;
1150 unix_ERR_code = ERRbadpath;
1152 return (UNIXERROR(ERRDOS,ERRnofids));
1154 return(ERROR(ERRDOS,ERRnofids));
1158 DEBUG(4,("dptr_num is %d\n",dptr_num));
1160 if (ok)
1162 if ((dirtype&0x1F) == aVOLID)
1164 memcpy(p,status,21);
1165 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1166 dptr_fill(p+12,dptr_num);
1167 if (dptr_zero(p+12) && (status_len==0))
1168 numentries = 1;
1169 else
1170 numentries = 0;
1171 p += DIR_STRUCT_SIZE;
1173 else
1175 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1176 conn->dirpath,lp_dontdescend(SNUM(conn))));
1177 if (in_list(conn->dirpath,
1178 lp_dontdescend(SNUM(conn)),True))
1179 check_descend = True;
1181 for (i=numentries;(i<maxentries) && !finished;i++)
1183 finished =
1184 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1185 if (!finished)
1187 memcpy(p,status,21);
1188 make_dir_struct(p,mask,fname,size,mode,date);
1189 dptr_fill(p+12,dptr_num);
1190 numentries++;
1192 p += DIR_STRUCT_SIZE;
1199 SearchEmpty:
1201 if (numentries == 0 || !ok)
1203 CVAL(outbuf,smb_rcls) = ERRDOS;
1204 SSVAL(outbuf,smb_err,ERRnofiles);
1207 /* If we were called as SMBffirst with smb_search_id == NULL
1208 and no entries were found then return error and close dirptr
1209 (X/Open spec) */
1211 if(ok && expect_close && numentries == 0 && status_len == 0)
1213 CVAL(outbuf,smb_rcls) = ERRDOS;
1214 SSVAL(outbuf,smb_err,ERRnofiles);
1215 /* Also close the dptr - we know it's gone */
1216 dptr_close(dptr_num);
1219 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1220 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1221 dptr_close(dptr_num);
1223 SSVAL(outbuf,smb_vwv0,numentries);
1224 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1225 CVAL(smb_buf(outbuf),0) = 5;
1226 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1228 if (Protocol >= PROTOCOL_NT1) {
1229 uint16 flg2 = SVAL(outbuf,smb_flg2);
1230 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1233 outsize += DIR_STRUCT_SIZE*numentries;
1234 smb_setlen(outbuf,outsize - 4);
1236 if ((! *directory) && dptr_path(dptr_num))
1237 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1239 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1240 smb_fn_name(CVAL(inbuf,smb_com)),
1241 mask, directory, dirtype, numentries, maxentries ) );
1243 return(outsize);
1247 /****************************************************************************
1248 reply to a fclose (stop directory search)
1249 ****************************************************************************/
1250 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1252 int outsize = 0;
1253 int status_len;
1254 char *path;
1255 char status[21];
1256 int dptr_num= -1;
1258 outsize = set_message(outbuf,1,0,True);
1259 path = smb_buf(inbuf) + 1;
1260 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1263 if (status_len == 0)
1264 return(ERROR(ERRSRV,ERRsrverror));
1266 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1268 if(dptr_fetch(status+12,&dptr_num)) {
1269 /* Close the dptr - we know it's gone */
1270 dptr_close(dptr_num);
1273 SSVAL(outbuf,smb_vwv0,0);
1275 DEBUG(3,("search close\n"));
1277 return(outsize);
1281 /****************************************************************************
1282 reply to an open
1283 ****************************************************************************/
1285 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1287 pstring fname;
1288 int outsize = 0;
1289 int fmode=0;
1290 int share_mode;
1291 SMB_OFF_T size = 0;
1292 time_t mtime=0;
1293 mode_t unixmode;
1294 int rmode=0;
1295 SMB_STRUCT_STAT sbuf;
1296 BOOL bad_path = False;
1297 files_struct *fsp;
1298 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1300 share_mode = SVAL(inbuf,smb_vwv0);
1302 pstrcpy(fname,smb_buf(inbuf)+1);
1303 unix_convert(fname,conn,0,&bad_path,NULL);
1305 fsp = file_new();
1306 if (!fsp)
1307 return(ERROR(ERRSRV,ERRnofids));
1309 if (!check_name(fname,conn))
1311 if((errno == ENOENT) && bad_path)
1313 unix_ERR_class = ERRDOS;
1314 unix_ERR_code = ERRbadpath;
1316 file_free(fsp);
1317 return(UNIXERROR(ERRDOS,ERRnoaccess));
1320 unixmode = unix_mode(conn,aARCH);
1322 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1323 unixmode, oplock_request,&rmode,NULL);
1325 if (!fsp->open)
1327 if((errno == ENOENT) && bad_path)
1329 unix_ERR_class = ERRDOS;
1330 unix_ERR_code = ERRbadpath;
1332 file_free(fsp);
1333 return(UNIXERROR(ERRDOS,ERRnoaccess));
1336 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1337 close_file(fsp,False);
1338 return(ERROR(ERRDOS,ERRnoaccess));
1341 size = sbuf.st_size;
1342 fmode = dos_mode(conn,fname,&sbuf);
1343 mtime = sbuf.st_mtime;
1345 if (fmode & aDIR) {
1346 DEBUG(3,("attempt to open a directory %s\n",fname));
1347 close_file(fsp,False);
1348 return(ERROR(ERRDOS,ERRnoaccess));
1351 outsize = set_message(outbuf,7,0,True);
1352 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1353 SSVAL(outbuf,smb_vwv1,fmode);
1354 if(lp_dos_filetime_resolution(SNUM(conn)) )
1355 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1356 else
1357 put_dos_date3(outbuf,smb_vwv2,mtime);
1358 SIVAL(outbuf,smb_vwv4,(uint32)size);
1359 SSVAL(outbuf,smb_vwv6,rmode);
1361 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1362 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1365 if(fsp->granted_oplock)
1366 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1367 return(outsize);
1371 /****************************************************************************
1372 reply to an open and X
1373 ****************************************************************************/
1374 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1376 pstring fname;
1377 int smb_mode = SVAL(inbuf,smb_vwv3);
1378 int smb_attr = SVAL(inbuf,smb_vwv5);
1379 /* Breakout the oplock request bits so we can set the
1380 reply bits separately. */
1381 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1382 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1383 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1384 #if 0
1385 int open_flags = SVAL(inbuf,smb_vwv2);
1386 int smb_sattr = SVAL(inbuf,smb_vwv4);
1387 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1388 #endif
1389 int smb_ofun = SVAL(inbuf,smb_vwv8);
1390 mode_t unixmode;
1391 SMB_OFF_T size=0;
1392 int fmode=0,mtime=0,rmode=0;
1393 SMB_STRUCT_STAT sbuf;
1394 int smb_action = 0;
1395 BOOL bad_path = False;
1396 files_struct *fsp;
1398 /* If it's an IPC, pass off the pipe handler. */
1399 if (IS_IPC(conn) && lp_nt_pipe_support())
1400 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1402 /* XXXX we need to handle passed times, sattr and flags */
1404 pstrcpy(fname,smb_buf(inbuf));
1405 unix_convert(fname,conn,0,&bad_path,NULL);
1407 fsp = file_new();
1408 if (!fsp)
1409 return(ERROR(ERRSRV,ERRnofids));
1411 if (!check_name(fname,conn))
1413 if((errno == ENOENT) && bad_path)
1415 unix_ERR_class = ERRDOS;
1416 unix_ERR_code = ERRbadpath;
1418 file_free(fsp);
1419 return(UNIXERROR(ERRDOS,ERRnoaccess));
1422 unixmode = unix_mode(conn,smb_attr | aARCH);
1424 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1425 oplock_request, &rmode,&smb_action);
1427 if (!fsp->open)
1429 if((errno == ENOENT) && bad_path)
1431 unix_ERR_class = ERRDOS;
1432 unix_ERR_code = ERRbadpath;
1434 file_free(fsp);
1435 return(UNIXERROR(ERRDOS,ERRnoaccess));
1438 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1439 close_file(fsp,False);
1440 return(ERROR(ERRDOS,ERRnoaccess));
1443 size = sbuf.st_size;
1444 fmode = dos_mode(conn,fname,&sbuf);
1445 mtime = sbuf.st_mtime;
1446 if (fmode & aDIR) {
1447 close_file(fsp,False);
1448 return(ERROR(ERRDOS,ERRnoaccess));
1451 /* If the caller set the extended oplock request bit
1452 and we granted one (by whatever means) - set the
1453 correct bit for extended oplock reply.
1456 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1457 smb_action |= EXTENDED_OPLOCK_GRANTED;
1460 if(ex_oplock_request && fsp->granted_oplock) {
1461 smb_action |= EXTENDED_OPLOCK_GRANTED;
1464 /* If the caller set the core oplock request bit
1465 and we granted one (by whatever means) - set the
1466 correct bit for core oplock reply.
1469 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1470 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1473 if(core_oplock_request && fsp->granted_oplock) {
1474 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1477 set_message(outbuf,15,0,True);
1478 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1479 SSVAL(outbuf,smb_vwv3,fmode);
1480 if(lp_dos_filetime_resolution(SNUM(conn)) )
1481 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1482 else
1483 put_dos_date3(outbuf,smb_vwv4,mtime);
1484 SIVAL(outbuf,smb_vwv6,(uint32)size);
1485 SSVAL(outbuf,smb_vwv8,rmode);
1486 SSVAL(outbuf,smb_vwv11,smb_action);
1488 return chain_reply(inbuf,outbuf,length,bufsize);
1492 /****************************************************************************
1493 reply to a SMBulogoffX
1494 ****************************************************************************/
1495 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1497 uint16 vuid = SVAL(inbuf,smb_uid);
1498 user_struct *vuser = get_valid_user_struct(vuid);
1500 if(vuser == 0) {
1501 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1504 /* in user level security we are supposed to close any files
1505 open by this user */
1506 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1507 file_close_user(vuid);
1510 invalidate_vuid(vuid);
1512 set_message(outbuf,2,0,True);
1514 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1516 return chain_reply(inbuf,outbuf,length,bufsize);
1520 /****************************************************************************
1521 reply to a mknew or a create
1522 ****************************************************************************/
1523 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1525 pstring fname;
1526 int com;
1527 int outsize = 0;
1528 int createmode;
1529 mode_t unixmode;
1530 int ofun = 0;
1531 BOOL bad_path = False;
1532 files_struct *fsp;
1533 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1535 com = SVAL(inbuf,smb_com);
1537 createmode = SVAL(inbuf,smb_vwv0);
1538 pstrcpy(fname,smb_buf(inbuf)+1);
1539 unix_convert(fname,conn,0,&bad_path,NULL);
1541 if (createmode & aVOLID)
1543 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1546 unixmode = unix_mode(conn,createmode);
1548 fsp = file_new();
1549 if (!fsp)
1550 return(ERROR(ERRSRV,ERRnofids));
1552 if (!check_name(fname,conn))
1554 if((errno == ENOENT) && bad_path)
1556 unix_ERR_class = ERRDOS;
1557 unix_ERR_code = ERRbadpath;
1559 file_free(fsp);
1560 return(UNIXERROR(ERRDOS,ERRnoaccess));
1563 if(com == SMBmknew)
1565 /* We should fail if file exists. */
1566 ofun = 0x10;
1568 else
1570 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1571 ofun = 0x12;
1574 /* Open file in dos compatibility share mode. */
1575 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1576 ofun, unixmode, oplock_request, NULL, NULL);
1578 if (!fsp->open)
1580 if((errno == ENOENT) && bad_path)
1582 unix_ERR_class = ERRDOS;
1583 unix_ERR_code = ERRbadpath;
1585 file_free(fsp);
1586 return(UNIXERROR(ERRDOS,ERRnoaccess));
1589 outsize = set_message(outbuf,1,0,True);
1590 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1592 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1593 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1596 if(fsp->granted_oplock)
1597 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1599 DEBUG( 2, ( "new file %s\n", fname ) );
1600 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1601 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1603 return(outsize);
1607 /****************************************************************************
1608 reply to a create temporary file
1609 ****************************************************************************/
1610 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1612 pstring fname;
1613 pstring fname2;
1614 int outsize = 0;
1615 int createmode;
1616 mode_t unixmode;
1617 BOOL bad_path = False;
1618 files_struct *fsp;
1619 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1621 createmode = SVAL(inbuf,smb_vwv0);
1622 pstrcpy(fname,smb_buf(inbuf)+1);
1623 pstrcat(fname,"/TMXXXXXX");
1624 unix_convert(fname,conn,0,&bad_path,NULL);
1626 unixmode = unix_mode(conn,createmode);
1628 fsp = file_new();
1629 if (fsp)
1630 return(ERROR(ERRSRV,ERRnofids));
1632 if (!check_name(fname,conn))
1634 if((errno == ENOENT) && bad_path)
1636 unix_ERR_class = ERRDOS;
1637 unix_ERR_code = ERRbadpath;
1639 file_free(fsp);
1640 return(UNIXERROR(ERRDOS,ERRnoaccess));
1643 pstrcpy(fname2,(char *)mktemp(fname));
1645 /* Open file in dos compatibility share mode. */
1646 /* We should fail if file exists. */
1647 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1648 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1650 if (!fsp->open)
1652 if((errno == ENOENT) && bad_path)
1654 unix_ERR_class = ERRDOS;
1655 unix_ERR_code = ERRbadpath;
1657 file_free(fsp);
1658 return(UNIXERROR(ERRDOS,ERRnoaccess));
1661 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1662 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1663 CVAL(smb_buf(outbuf),0) = 4;
1664 pstrcpy(smb_buf(outbuf) + 1,fname2);
1666 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1667 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1670 if(fsp->granted_oplock)
1671 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1673 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1674 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1675 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1677 return(outsize);
1681 /*******************************************************************
1682 check if a user is allowed to delete a file
1683 ********************************************************************/
1684 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1686 SMB_STRUCT_STAT sbuf;
1687 int fmode;
1689 if (!CAN_WRITE(conn)) return(False);
1691 if (dos_lstat(fname,&sbuf) != 0) return(False);
1692 fmode = dos_mode(conn,fname,&sbuf);
1693 if (fmode & aDIR) return(False);
1694 if (!lp_delete_readonly(SNUM(conn))) {
1695 if (fmode & aRONLY) return(False);
1697 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1698 return(False);
1699 if (!check_file_sharing(conn,fname,False)) return(False);
1700 return(True);
1703 /****************************************************************************
1704 reply to a unlink
1705 ****************************************************************************/
1706 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1708 int outsize = 0;
1709 pstring name;
1710 int dirtype;
1711 pstring directory;
1712 pstring mask;
1713 char *p;
1714 int count=0;
1715 int error = ERRnoaccess;
1716 BOOL has_wild;
1717 BOOL exists=False;
1718 BOOL bad_path = False;
1720 *directory = *mask = 0;
1722 dirtype = SVAL(inbuf,smb_vwv0);
1724 pstrcpy(name,smb_buf(inbuf) + 1);
1726 DEBUG(3,("reply_unlink : %s\n",name));
1728 unix_convert(name,conn,0,&bad_path,NULL);
1730 p = strrchr(name,'/');
1731 if (!p) {
1732 pstrcpy(directory,"./");
1733 pstrcpy(mask,name);
1734 } else {
1735 *p = 0;
1736 pstrcpy(directory,name);
1737 pstrcpy(mask,p+1);
1740 if (is_mangled(mask))
1741 check_mangled_cache( mask );
1743 has_wild = strchr(mask,'*') || strchr(mask,'?');
1745 if (!has_wild) {
1746 pstrcat(directory,"/");
1747 pstrcat(directory,mask);
1748 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1749 count++;
1750 if (!count)
1751 exists = file_exist(directory,NULL);
1752 } else {
1753 void *dirptr = NULL;
1754 char *dname;
1756 if (check_name(directory,conn))
1757 dirptr = OpenDir(conn, directory, True);
1759 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1760 the pattern matches against the long name, otherwise the short name
1761 We don't implement this yet XXXX
1764 if (dirptr)
1766 error = ERRbadfile;
1768 if (strequal(mask,"????????.???"))
1769 pstrcpy(mask,"*");
1771 while ((dname = ReadDirName(dirptr)))
1773 pstring fname;
1774 pstrcpy(fname,dname);
1776 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1778 error = ERRnoaccess;
1779 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1780 if (!can_delete(fname,conn,dirtype)) continue;
1781 if (!dos_unlink(fname)) count++;
1782 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1784 CloseDir(dirptr);
1788 if (count == 0) {
1789 if (exists)
1790 return(ERROR(ERRDOS,error));
1791 else
1793 if((errno == ENOENT) && bad_path)
1795 unix_ERR_class = ERRDOS;
1796 unix_ERR_code = ERRbadpath;
1798 return(UNIXERROR(ERRDOS,error));
1802 outsize = set_message(outbuf,0,0,True);
1804 return(outsize);
1808 /****************************************************************************
1809 reply to a readbraw (core+ protocol)
1810 ****************************************************************************/
1811 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1813 size_t maxcount,mincount;
1814 size_t nread = 0;
1815 SMB_OFF_T startpos;
1816 char *header = outbuf;
1817 ssize_t ret=0;
1818 files_struct *fsp;
1821 * Special check if an oplock break has been issued
1822 * and the readraw request croses on the wire, we must
1823 * return a zero length response here.
1826 if(global_oplock_break)
1828 _smb_setlen(header,0);
1829 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1830 DEBUG(5,("readbraw - oplock break finished\n"));
1831 return -1;
1834 fsp = file_fsp(inbuf,smb_vwv0);
1836 startpos = IVAL(inbuf,smb_vwv1);
1837 #ifdef LARGE_SMB_OFF_T
1838 if(CVAL(inbuf,smb_wct) == 10) {
1840 * This is a large offset (64 bit) read.
1842 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1843 if(startpos < 0) {
1844 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1845 (double)startpos ));
1846 _smb_setlen(header,0);
1847 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1848 return(-1);
1851 #endif /* LARGE_SMB_OFF_T */
1852 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1853 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1855 /* ensure we don't overrun the packet size */
1856 maxcount = MIN(65535,maxcount);
1857 maxcount = MAX(mincount,maxcount);
1859 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1860 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1861 _smb_setlen(header,0);
1862 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1863 return(-1);
1866 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1868 SMB_OFF_T size = fsp->size;
1869 SMB_OFF_T sizeneeded = startpos + maxcount;
1871 if (size < sizeneeded)
1873 SMB_STRUCT_STAT st;
1874 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1875 size = st.st_size;
1876 if (!fsp->can_write)
1877 fsp->size = size;
1880 nread = MIN(maxcount,(size - startpos));
1883 if (nread < mincount)
1884 nread = 0;
1886 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1887 fsp->fnum, (double)startpos,
1888 maxcount, mincount, nread ) );
1890 #if UNSAFE_READRAW
1892 BOOL seek_fail = False;
1893 int predict=0;
1894 _smb_setlen(header,nread);
1896 #if USE_READ_PREDICTION
1897 if (!fsp->can_write)
1898 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1899 #endif /* USE_READ_PREDICTION */
1901 if ((nread-predict) > 0) {
1902 if(seek_file(fsp,startpos + predict) == -1) {
1903 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1904 ret = 0;
1905 seek_fail = True;
1909 if(!seek_fail)
1910 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1911 (SMB_OFF_T)(nread-predict),header,4+predict,
1912 startpos+predict);
1915 if (ret != nread+4)
1916 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1917 fsp->fsp_name,startpos,nread,ret));
1919 #else /* UNSAFE_READRAW */
1920 ret = read_file(fsp,header+4,startpos,nread);
1921 if (ret < mincount) ret = 0;
1923 _smb_setlen(header,ret);
1924 transfer_file(0,Client,0,header,4+ret,0);
1925 #endif /* UNSAFE_READRAW */
1927 DEBUG(5,("readbraw finished\n"));
1928 return -1;
1932 /****************************************************************************
1933 reply to a lockread (core+ protocol)
1934 ****************************************************************************/
1935 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1937 ssize_t nread = -1;
1938 char *data;
1939 int outsize = 0;
1940 SMB_OFF_T startpos;
1941 size_t numtoread;
1942 int eclass;
1943 uint32 ecode;
1944 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1946 CHECK_FSP(fsp,conn);
1947 CHECK_READ(fsp);
1948 CHECK_ERROR(fsp);
1950 numtoread = SVAL(inbuf,smb_vwv1);
1951 startpos = IVAL(inbuf,smb_vwv2);
1953 outsize = set_message(outbuf,5,3,True);
1954 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1955 data = smb_buf(outbuf) + 3;
1957 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1958 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1960 * A blocking lock was requested. Package up
1961 * this smb into a queued request and push it
1962 * onto the blocking lock queue.
1964 if(push_blocking_lock_request(inbuf, length, -1, 0))
1965 return -1;
1967 return (ERROR(eclass,ecode));
1970 nread = read_file(fsp,data,startpos,numtoread);
1972 if (nread < 0)
1973 return(UNIXERROR(ERRDOS,ERRnoaccess));
1975 outsize += nread;
1976 SSVAL(outbuf,smb_vwv0,nread);
1977 SSVAL(outbuf,smb_vwv5,nread+3);
1978 SSVAL(smb_buf(outbuf),1,nread);
1980 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1981 fsp->fnum, numtoread, nread ) );
1983 return(outsize);
1987 /****************************************************************************
1988 reply to a read
1989 ****************************************************************************/
1990 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1992 size_t numtoread;
1993 ssize_t nread = 0;
1994 char *data;
1995 SMB_OFF_T startpos;
1996 int outsize = 0;
1997 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1999 CHECK_FSP(fsp,conn);
2000 CHECK_READ(fsp);
2001 CHECK_ERROR(fsp);
2003 numtoread = SVAL(inbuf,smb_vwv1);
2004 startpos = IVAL(inbuf,smb_vwv2);
2006 outsize = set_message(outbuf,5,3,True);
2007 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2008 data = smb_buf(outbuf) + 3;
2010 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2011 return(ERROR(ERRDOS,ERRlock));
2013 if (numtoread > 0)
2014 nread = read_file(fsp,data,startpos,numtoread);
2016 if (nread < 0)
2017 return(UNIXERROR(ERRDOS,ERRnoaccess));
2019 outsize += nread;
2020 SSVAL(outbuf,smb_vwv0,nread);
2021 SSVAL(outbuf,smb_vwv5,nread+3);
2022 CVAL(smb_buf(outbuf),0) = 1;
2023 SSVAL(smb_buf(outbuf),1,nread);
2025 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2026 fsp->fnum, numtoread, nread ) );
2028 return(outsize);
2032 /****************************************************************************
2033 reply to a read and X
2034 ****************************************************************************/
2035 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2037 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2038 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2039 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2040 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2041 ssize_t nread = -1;
2042 char *data;
2044 /* If it's an IPC, pass off the pipe handler. */
2045 if (IS_IPC(conn))
2046 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2048 CHECK_FSP(fsp,conn);
2049 CHECK_READ(fsp);
2050 CHECK_ERROR(fsp);
2052 set_message(outbuf,12,0,True);
2053 data = smb_buf(outbuf);
2055 #ifdef LARGE_SMB_OFF_T
2056 if(CVAL(inbuf,smb_wct) == 12) {
2058 * This is a large offset (64 bit) read.
2060 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2062 #endif /* LARGE_SMB_OFF_T */
2064 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2065 return(ERROR(ERRDOS,ERRlock));
2066 nread = read_file(fsp,data,startpos,smb_maxcnt);
2068 if (nread < 0)
2069 return(UNIXERROR(ERRDOS,ERRnoaccess));
2071 SSVAL(outbuf,smb_vwv5,nread);
2072 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2073 SSVAL(smb_buf(outbuf),-2,nread);
2075 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2076 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2078 return chain_reply(inbuf,outbuf,length,bufsize);
2081 /****************************************************************************
2082 reply to a writebraw (core+ or LANMAN1.0 protocol)
2083 ****************************************************************************/
2084 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2086 ssize_t nwritten=0;
2087 ssize_t total_written=0;
2088 size_t numtowrite=0;
2089 size_t tcount;
2090 SMB_OFF_T startpos;
2091 char *data=NULL;
2092 BOOL write_through;
2093 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2094 int outsize = 0;
2096 CHECK_FSP(fsp,conn);
2097 CHECK_WRITE(fsp);
2098 CHECK_ERROR(fsp);
2100 tcount = IVAL(inbuf,smb_vwv1);
2101 startpos = IVAL(inbuf,smb_vwv3);
2102 write_through = BITSETW(inbuf+smb_vwv7,0);
2104 /* We have to deal with slightly different formats depending
2105 on whether we are using the core+ or lanman1.0 protocol */
2106 if(Protocol <= PROTOCOL_COREPLUS) {
2107 numtowrite = SVAL(smb_buf(inbuf),-2);
2108 data = smb_buf(inbuf);
2109 } else {
2110 numtowrite = SVAL(inbuf,smb_vwv10);
2111 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2114 /* force the error type */
2115 CVAL(inbuf,smb_com) = SMBwritec;
2116 CVAL(outbuf,smb_com) = SMBwritec;
2118 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2119 return(ERROR(ERRDOS,ERRlock));
2121 if (seek_file(fsp,startpos) == -1) {
2122 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2123 return(UNIXERROR(ERRDOS,ERRnoaccess));
2126 if (numtowrite>0)
2127 nwritten = write_file(fsp,data,numtowrite);
2129 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2130 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2132 if (nwritten < numtowrite)
2133 return(UNIXERROR(ERRHRD,ERRdiskfull));
2135 total_written = nwritten;
2137 /* Return a message to the redirector to tell it
2138 to send more bytes */
2139 CVAL(outbuf,smb_com) = SMBwritebraw;
2140 SSVALS(outbuf,smb_vwv0,-1);
2141 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2142 send_smb(Client,outbuf);
2144 /* Now read the raw data into the buffer and write it */
2145 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2146 exit_server("secondary writebraw failed");
2149 /* Even though this is not an smb message, smb_len
2150 returns the generic length of an smb message */
2151 numtowrite = smb_len(inbuf);
2153 if (tcount > nwritten+numtowrite) {
2154 DEBUG(3,("Client overestimated the write %d %d %d\n",
2155 tcount,nwritten,numtowrite));
2158 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2159 startpos+nwritten);
2160 total_written += nwritten;
2162 /* Set up outbuf to return the correct return */
2163 outsize = set_message(outbuf,1,0,True);
2164 CVAL(outbuf,smb_com) = SMBwritec;
2165 SSVAL(outbuf,smb_vwv0,total_written);
2167 if (nwritten < (ssize_t)numtowrite) {
2168 CVAL(outbuf,smb_rcls) = ERRHRD;
2169 SSVAL(outbuf,smb_err,ERRdiskfull);
2172 if (lp_syncalways(SNUM(conn)) || write_through)
2173 sync_file(conn,fsp);
2175 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2176 fsp->fnum, (double)startpos, numtowrite, total_written));
2178 /* we won't return a status if write through is not selected - this
2179 follows what WfWg does */
2180 if (!write_through && total_written==tcount)
2181 return(-1);
2183 return(outsize);
2186 /****************************************************************************
2187 reply to a writeunlock (core+)
2188 ****************************************************************************/
2189 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2191 ssize_t nwritten = -1;
2192 size_t numtowrite;
2193 SMB_OFF_T startpos;
2194 char *data;
2195 int eclass;
2196 uint32 ecode;
2197 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2198 int outsize = 0;
2200 CHECK_FSP(fsp,conn);
2201 CHECK_WRITE(fsp);
2202 CHECK_ERROR(fsp);
2204 numtowrite = SVAL(inbuf,smb_vwv1);
2205 startpos = IVAL(inbuf,smb_vwv2);
2206 data = smb_buf(inbuf) + 3;
2208 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2209 return(ERROR(ERRDOS,ERRlock));
2211 if(seek_file(fsp,startpos) == -1)
2212 return(UNIXERROR(ERRDOS,ERRnoaccess));
2214 /* The special X/Open SMB protocol handling of
2215 zero length writes is *NOT* done for
2216 this call */
2217 if(numtowrite == 0)
2218 nwritten = 0;
2219 else
2220 nwritten = write_file(fsp,data,numtowrite);
2222 if (lp_syncalways(SNUM(conn)))
2223 sync_file(conn,fsp);
2225 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2226 return(UNIXERROR(ERRDOS,ERRnoaccess));
2228 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2229 return(ERROR(eclass,ecode));
2231 outsize = set_message(outbuf,1,0,True);
2233 SSVAL(outbuf,smb_vwv0,nwritten);
2235 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2236 fsp->fnum, numtowrite, nwritten ) );
2238 return(outsize);
2241 /****************************************************************************
2242 reply to a write
2243 ****************************************************************************/
2244 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2246 size_t numtowrite;
2247 ssize_t nwritten = -1;
2248 SMB_OFF_T startpos;
2249 char *data;
2250 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2251 int outsize = 0;
2253 CHECK_FSP(fsp,conn);
2254 CHECK_WRITE(fsp);
2255 CHECK_ERROR(fsp);
2257 numtowrite = SVAL(inbuf,smb_vwv1);
2258 startpos = IVAL(inbuf,smb_vwv2);
2259 data = smb_buf(inbuf) + 3;
2261 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2262 return(ERROR(ERRDOS,ERRlock));
2264 if(seek_file(fsp,startpos) == -1)
2265 return(UNIXERROR(ERRDOS,ERRnoaccess));
2267 /* X/Open SMB protocol says that if smb_vwv1 is
2268 zero then the file size should be extended or
2269 truncated to the size given in smb_vwv[2-3] */
2270 if(numtowrite == 0)
2271 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2272 else
2273 nwritten = write_file(fsp,data,numtowrite);
2275 if (lp_syncalways(SNUM(conn)))
2276 sync_file(conn,fsp);
2278 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2279 return(UNIXERROR(ERRDOS,ERRnoaccess));
2281 outsize = set_message(outbuf,1,0,True);
2283 SSVAL(outbuf,smb_vwv0,nwritten);
2285 if (nwritten < (ssize_t)numtowrite) {
2286 CVAL(outbuf,smb_rcls) = ERRHRD;
2287 SSVAL(outbuf,smb_err,ERRdiskfull);
2290 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2291 fsp->fnum, numtowrite, nwritten));
2293 return(outsize);
2297 /****************************************************************************
2298 reply to a write and X
2299 ****************************************************************************/
2300 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2302 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2303 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2304 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2305 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2306 ssize_t nwritten = -1;
2307 int smb_doff = SVAL(inbuf,smb_vwv11);
2308 char *data;
2310 /* If it's an IPC, pass off the pipe handler. */
2311 if (IS_IPC(conn))
2312 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2314 CHECK_FSP(fsp,conn);
2315 CHECK_WRITE(fsp);
2316 CHECK_ERROR(fsp);
2318 data = smb_base(inbuf) + smb_doff;
2320 #ifdef LARGE_SMB_OFF_T
2321 if(CVAL(inbuf,smb_wct) == 14) {
2323 * This is a large offset (64 bit) write.
2325 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2327 #endif /* LARGE_SMB_OFF_T */
2329 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2330 return(ERROR(ERRDOS,ERRlock));
2332 if(seek_file(fsp,startpos) == -1)
2333 return(UNIXERROR(ERRDOS,ERRnoaccess));
2335 /* X/Open SMB protocol says that, unlike SMBwrite
2336 if the length is zero then NO truncation is
2337 done, just a write of zero. To truncate a file,
2338 use SMBwrite. */
2339 if(numtowrite == 0)
2340 nwritten = 0;
2341 else
2342 nwritten = write_file(fsp,data,numtowrite);
2344 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2345 return(UNIXERROR(ERRDOS,ERRnoaccess));
2347 set_message(outbuf,6,0,True);
2349 SSVAL(outbuf,smb_vwv2,nwritten);
2351 if (nwritten < (ssize_t)numtowrite) {
2352 CVAL(outbuf,smb_rcls) = ERRHRD;
2353 SSVAL(outbuf,smb_err,ERRdiskfull);
2356 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2357 fsp->fnum, numtowrite, nwritten));
2359 if (lp_syncalways(SNUM(conn)) || write_through)
2360 sync_file(conn,fsp);
2362 return chain_reply(inbuf,outbuf,length,bufsize);
2366 /****************************************************************************
2367 reply to a lseek
2368 ****************************************************************************/
2369 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2371 SMB_OFF_T startpos;
2372 SMB_OFF_T res= -1;
2373 int mode,umode;
2374 int outsize = 0;
2375 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2377 CHECK_FSP(fsp,conn);
2378 CHECK_ERROR(fsp);
2380 mode = SVAL(inbuf,smb_vwv1) & 3;
2381 startpos = IVAL(inbuf,smb_vwv2);
2383 switch (mode & 3)
2385 case 0: umode = SEEK_SET; break;
2386 case 1: umode = SEEK_CUR; break;
2387 case 2: umode = SEEK_END; break;
2388 default:
2389 umode = SEEK_SET; break;
2392 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2393 return(UNIXERROR(ERRDOS,ERRnoaccess));
2395 fsp->pos = res;
2397 outsize = set_message(outbuf,2,0,True);
2398 SIVALS(outbuf,smb_vwv0,res);
2400 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2401 fsp->fnum, (double)startpos, mode));
2403 return(outsize);
2406 /****************************************************************************
2407 reply to a flush
2408 ****************************************************************************/
2409 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2411 int outsize = set_message(outbuf,0,0,True);
2412 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2414 if (fsp) {
2415 CHECK_FSP(fsp,conn);
2416 CHECK_ERROR(fsp);
2419 if (!fsp) {
2420 file_sync_all(conn);
2421 } else {
2422 sync_file(conn,fsp);
2425 DEBUG(3,("flush\n"));
2426 return(outsize);
2430 /****************************************************************************
2431 reply to a exit
2432 ****************************************************************************/
2433 int reply_exit(connection_struct *conn,
2434 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2436 int outsize = set_message(outbuf,0,0,True);
2437 DEBUG(3,("exit\n"));
2439 return(outsize);
2443 /****************************************************************************
2444 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2445 ****************************************************************************/
2446 int reply_close(connection_struct *conn,
2447 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2449 int outsize = 0;
2450 time_t mtime;
2451 int32 eclass = 0, err = 0;
2452 files_struct *fsp = NULL;
2454 outsize = set_message(outbuf,0,0,True);
2456 /* If it's an IPC, pass off to the pipe handler. */
2457 if (IS_IPC(conn)) {
2458 return reply_pipe_close(conn, inbuf,outbuf);
2461 fsp = file_fsp(inbuf,smb_vwv0);
2464 * We can only use CHECK_FSP if we know it's not a directory.
2467 if(!fsp || !fsp->open || (fsp->conn != conn))
2468 return(ERROR(ERRDOS,ERRbadfid));
2470 if(HAS_CACHED_ERROR(fsp)) {
2471 eclass = fsp->wbmpx_ptr->wr_errclass;
2472 err = fsp->wbmpx_ptr->wr_error;
2475 if(fsp->is_directory) {
2477 * Special case - close NT SMB directory
2478 * handle.
2480 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2481 close_directory(fsp);
2482 } else {
2484 * Close ordinary file.
2486 mtime = make_unix_date3(inbuf+smb_vwv1);
2488 /* try and set the date */
2489 set_filetime(conn, fsp->fsp_name,mtime);
2491 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2492 fsp->fd_ptr->fd, fsp->fnum,
2493 conn->num_files_open));
2495 close_file(fsp,True);
2498 /* We have a cached error */
2499 if(eclass || err)
2500 return(ERROR(eclass,err));
2502 return(outsize);
2506 /****************************************************************************
2507 reply to a writeclose (Core+ protocol)
2508 ****************************************************************************/
2509 int reply_writeclose(connection_struct *conn,
2510 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2512 size_t numtowrite;
2513 ssize_t nwritten = -1;
2514 int outsize = 0;
2515 SMB_OFF_T startpos;
2516 char *data;
2517 time_t mtime;
2518 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2520 CHECK_FSP(fsp,conn);
2521 CHECK_WRITE(fsp);
2522 CHECK_ERROR(fsp);
2524 numtowrite = SVAL(inbuf,smb_vwv1);
2525 startpos = IVAL(inbuf,smb_vwv2);
2526 mtime = make_unix_date3(inbuf+smb_vwv4);
2527 data = smb_buf(inbuf) + 1;
2529 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2530 return(ERROR(ERRDOS,ERRlock));
2532 if(seek_file(fsp,startpos) == -1)
2533 return(UNIXERROR(ERRDOS,ERRnoaccess));
2535 nwritten = write_file(fsp,data,numtowrite);
2537 set_filetime(conn, fsp->fsp_name,mtime);
2539 close_file(fsp,True);
2541 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2542 fsp->fnum, numtowrite, nwritten,
2543 conn->num_files_open));
2545 if (nwritten <= 0)
2546 return(UNIXERROR(ERRDOS,ERRnoaccess));
2548 outsize = set_message(outbuf,1,0,True);
2550 SSVAL(outbuf,smb_vwv0,nwritten);
2551 return(outsize);
2555 /****************************************************************************
2556 reply to a lock
2557 ****************************************************************************/
2558 int reply_lock(connection_struct *conn,
2559 char *inbuf,char *outbuf, int length, int dum_buffsize)
2561 int outsize = set_message(outbuf,0,0,True);
2562 SMB_OFF_T count,offset;
2563 int eclass;
2564 uint32 ecode;
2565 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2567 CHECK_FSP(fsp,conn);
2568 CHECK_ERROR(fsp);
2570 count = IVAL(inbuf,smb_vwv1);
2571 offset = IVAL(inbuf,smb_vwv3);
2573 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2574 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2576 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2577 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2579 * A blocking lock was requested. Package up
2580 * this smb into a queued request and push it
2581 * onto the blocking lock queue.
2583 if(push_blocking_lock_request(inbuf, length, -1, 0))
2584 return -1;
2586 return (ERROR(eclass,ecode));
2589 return(outsize);
2593 /****************************************************************************
2594 reply to a unlock
2595 ****************************************************************************/
2596 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2598 int outsize = set_message(outbuf,0,0,True);
2599 SMB_OFF_T count,offset;
2600 int eclass;
2601 uint32 ecode;
2602 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2604 CHECK_FSP(fsp,conn);
2605 CHECK_ERROR(fsp);
2607 count = IVAL(inbuf,smb_vwv1);
2608 offset = IVAL(inbuf,smb_vwv3);
2610 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2611 return (ERROR(eclass,ecode));
2613 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2614 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2616 return(outsize);
2620 /****************************************************************************
2621 reply to a tdis
2622 ****************************************************************************/
2623 int reply_tdis(connection_struct *conn,
2624 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2626 int outsize = set_message(outbuf,0,0,True);
2627 uint16 vuid;
2629 vuid = SVAL(inbuf,smb_uid);
2631 if (!conn) {
2632 DEBUG(4,("Invalid connection in tdis\n"));
2633 return(ERROR(ERRSRV,ERRinvnid));
2636 conn->used = False;
2638 close_cnum(conn,vuid);
2640 return outsize;
2645 /****************************************************************************
2646 reply to a echo
2647 ****************************************************************************/
2648 int reply_echo(connection_struct *conn,
2649 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2651 int smb_reverb = SVAL(inbuf,smb_vwv0);
2652 int seq_num;
2653 int data_len = smb_buflen(inbuf);
2654 int outsize = set_message(outbuf,1,data_len,True);
2656 /* copy any incoming data back out */
2657 if (data_len > 0)
2658 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2660 if (smb_reverb > 100) {
2661 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2662 smb_reverb = 100;
2665 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2666 SSVAL(outbuf,smb_vwv0,seq_num);
2668 smb_setlen(outbuf,outsize - 4);
2670 send_smb(Client,outbuf);
2673 DEBUG(3,("echo %d times\n", smb_reverb));
2675 return -1;
2679 /****************************************************************************
2680 reply to a printopen
2681 ****************************************************************************/
2682 int reply_printopen(connection_struct *conn,
2683 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2685 pstring fname;
2686 pstring fname2;
2687 int outsize = 0;
2688 files_struct *fsp;
2690 *fname = *fname2 = 0;
2692 if (!CAN_PRINT(conn))
2693 return(ERROR(ERRDOS,ERRnoaccess));
2696 pstring s;
2697 char *p;
2698 pstrcpy(s,smb_buf(inbuf)+1);
2699 p = s;
2700 while (*p) {
2701 if (!(isalnum((int)*p) || strchr("._-",*p)))
2702 *p = 'X';
2703 p++;
2706 if (strlen(s) > 10) s[10] = 0;
2708 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2711 fsp = file_new();
2712 if (!fsp)
2713 return(ERROR(ERRSRV,ERRnofids));
2715 pstrcpy(fname2,(char *)mktemp(fname));
2717 if (!check_name(fname2,conn)) {
2718 file_free(fsp);
2719 return(ERROR(ERRDOS,ERRnoaccess));
2722 /* Open for exclusive use, write only. */
2723 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2724 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE), unix_mode(conn,0), 0, NULL, NULL);
2726 if (!fsp->open) {
2727 file_free(fsp);
2728 return(UNIXERROR(ERRDOS,ERRnoaccess));
2731 /* force it to be a print file */
2732 fsp->print_file = True;
2734 outsize = set_message(outbuf,1,0,True);
2735 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2737 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2738 fname2, fsp->fd_ptr->fd, fsp->fnum));
2740 return(outsize);
2744 /****************************************************************************
2745 reply to a printclose
2746 ****************************************************************************/
2747 int reply_printclose(connection_struct *conn,
2748 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2750 int outsize = set_message(outbuf,0,0,True);
2751 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2753 CHECK_FSP(fsp,conn);
2754 CHECK_ERROR(fsp);
2756 if (!CAN_PRINT(conn))
2757 return(ERROR(ERRDOS,ERRnoaccess));
2759 DEBUG(3,("printclose fd=%d fnum=%d\n",
2760 fsp->fd_ptr->fd,fsp->fnum));
2762 close_file(fsp,True);
2764 return(outsize);
2768 /****************************************************************************
2769 reply to a printqueue
2770 ****************************************************************************/
2771 int reply_printqueue(connection_struct *conn,
2772 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2774 int outsize = set_message(outbuf,2,3,True);
2775 int max_count = SVAL(inbuf,smb_vwv0);
2776 int start_index = SVAL(inbuf,smb_vwv1);
2778 /* we used to allow the client to get the cnum wrong, but that
2779 is really quite gross and only worked when there was only
2780 one printer - I think we should now only accept it if they
2781 get it right (tridge) */
2782 if (!CAN_PRINT(conn))
2783 return(ERROR(ERRDOS,ERRnoaccess));
2785 SSVAL(outbuf,smb_vwv0,0);
2786 SSVAL(outbuf,smb_vwv1,0);
2787 CVAL(smb_buf(outbuf),0) = 1;
2788 SSVAL(smb_buf(outbuf),1,0);
2790 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2791 start_index, max_count));
2794 print_queue_struct *queue = NULL;
2795 char *p = smb_buf(outbuf) + 3;
2796 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2797 int num_to_get = ABS(max_count);
2798 int first = (max_count>0?start_index:start_index+max_count+1);
2799 int i;
2801 if (first >= count)
2802 num_to_get = 0;
2803 else
2804 num_to_get = MIN(num_to_get,count-first);
2807 for (i=first;i<first+num_to_get;i++) {
2808 put_dos_date2(p,0,queue[i].time);
2809 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2810 SSVAL(p,5,printjob_encode(SNUM(conn),
2811 queue[i].job));
2812 SIVAL(p,7,queue[i].size);
2813 CVAL(p,11) = 0;
2814 StrnCpy(p+12,queue[i].user,16);
2815 p += 28;
2818 if (count > 0) {
2819 outsize = set_message(outbuf,2,28*count+3,False);
2820 SSVAL(outbuf,smb_vwv0,count);
2821 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2822 CVAL(smb_buf(outbuf),0) = 1;
2823 SSVAL(smb_buf(outbuf),1,28*count);
2826 if (queue) free(queue);
2828 DEBUG(3,("%d entries returned in queue\n",count));
2831 return(outsize);
2835 /****************************************************************************
2836 reply to a printwrite
2837 ****************************************************************************/
2838 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2840 int numtowrite;
2841 int outsize = set_message(outbuf,0,0,True);
2842 char *data;
2843 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2845 if (!CAN_PRINT(conn))
2846 return(ERROR(ERRDOS,ERRnoaccess));
2848 CHECK_FSP(fsp,conn);
2849 CHECK_WRITE(fsp);
2850 CHECK_ERROR(fsp);
2852 numtowrite = SVAL(smb_buf(inbuf),1);
2853 data = smb_buf(inbuf) + 3;
2855 if (write_file(fsp,data,numtowrite) != numtowrite)
2856 return(UNIXERROR(ERRDOS,ERRnoaccess));
2858 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2860 return(outsize);
2864 /****************************************************************************
2865 reply to a mkdir
2866 ****************************************************************************/
2867 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2869 pstring directory;
2870 int outsize,ret= -1;
2871 BOOL bad_path = False;
2873 pstrcpy(directory,smb_buf(inbuf) + 1);
2874 unix_convert(directory,conn,0,&bad_path,NULL);
2876 if (check_name(directory, conn))
2877 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2879 if (ret < 0)
2881 if((errno == ENOENT) && bad_path)
2883 unix_ERR_class = ERRDOS;
2884 unix_ERR_code = ERRbadpath;
2886 return(UNIXERROR(ERRDOS,ERRnoaccess));
2889 outsize = set_message(outbuf,0,0,True);
2891 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2893 return(outsize);
2896 /****************************************************************************
2897 Static function used by reply_rmdir to delete an entire directory
2898 tree recursively.
2899 ****************************************************************************/
2900 static BOOL recursive_rmdir(char *directory)
2902 char *dname = NULL;
2903 BOOL ret = False;
2904 void *dirptr = OpenDir(NULL, directory, False);
2906 if(dirptr == NULL)
2907 return True;
2909 while((dname = ReadDirName(dirptr)))
2911 pstring fullname;
2912 SMB_STRUCT_STAT st;
2914 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2915 continue;
2917 /* Construct the full name. */
2918 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2920 errno = ENOMEM;
2921 ret = True;
2922 break;
2924 pstrcpy(fullname, directory);
2925 pstrcat(fullname, "/");
2926 pstrcat(fullname, dname);
2928 if(dos_lstat(fullname, &st) != 0)
2930 ret = True;
2931 break;
2934 if(st.st_mode & S_IFDIR)
2936 if(recursive_rmdir(fullname)!=0)
2938 ret = True;
2939 break;
2941 if(dos_rmdir(fullname) != 0)
2943 ret = True;
2944 break;
2947 else if(dos_unlink(fullname) != 0)
2949 ret = True;
2950 break;
2953 CloseDir(dirptr);
2954 return ret;
2957 /****************************************************************************
2958 reply to a rmdir
2959 ****************************************************************************/
2960 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2962 pstring directory;
2963 int outsize = 0;
2964 BOOL ok = False;
2965 BOOL bad_path = False;
2967 pstrcpy(directory,smb_buf(inbuf) + 1);
2968 unix_convert(directory,conn, NULL,&bad_path,NULL);
2970 if (check_name(directory,conn))
2973 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2974 ok = (dos_rmdir(directory) == 0);
2975 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2977 /* Check to see if the only thing in this directory are
2978 vetoed files/directories. If so then delete them and
2979 retry. If we fail to delete any of them (and we *don't*
2980 do a recursive delete) then fail the rmdir. */
2981 BOOL all_veto_files = True;
2982 char *dname;
2983 void *dirptr = OpenDir(conn, directory, False);
2985 if(dirptr != NULL)
2987 int dirpos = TellDir(dirptr);
2988 while ((dname = ReadDirName(dirptr)))
2990 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2991 continue;
2992 if(!IS_VETO_PATH(conn, dname))
2994 all_veto_files = False;
2995 break;
2998 if(all_veto_files)
3000 SeekDir(dirptr,dirpos);
3001 while ((dname = ReadDirName(dirptr)))
3003 pstring fullname;
3004 SMB_STRUCT_STAT st;
3006 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3007 continue;
3009 /* Construct the full name. */
3010 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3012 errno = ENOMEM;
3013 break;
3015 pstrcpy(fullname, directory);
3016 pstrcat(fullname, "/");
3017 pstrcat(fullname, dname);
3019 if(dos_lstat(fullname, &st) != 0)
3020 break;
3021 if(st.st_mode & S_IFDIR)
3023 if(lp_recursive_veto_delete(SNUM(conn)))
3025 if(recursive_rmdir(fullname) != 0)
3026 break;
3028 if(dos_rmdir(fullname) != 0)
3029 break;
3031 else if(dos_unlink(fullname) != 0)
3032 break;
3034 CloseDir(dirptr);
3035 /* Retry the rmdir */
3036 ok = (dos_rmdir(directory) == 0);
3038 else
3039 CloseDir(dirptr);
3041 else
3042 errno = ENOTEMPTY;
3045 if (!ok)
3046 DEBUG(3,("couldn't remove directory %s : %s\n",
3047 directory,strerror(errno)));
3050 if (!ok)
3052 if((errno == ENOENT) && bad_path)
3054 unix_ERR_class = ERRDOS;
3055 unix_ERR_code = ERRbadpath;
3057 return(UNIXERROR(ERRDOS,ERRbadpath));
3060 outsize = set_message(outbuf,0,0,True);
3062 DEBUG( 3, ( "rmdir %s\n", directory ) );
3064 return(outsize);
3068 /*******************************************************************
3069 resolve wildcards in a filename rename
3070 ********************************************************************/
3071 static BOOL resolve_wildcards(char *name1,char *name2)
3073 fstring root1,root2;
3074 fstring ext1,ext2;
3075 char *p,*p2;
3077 name1 = strrchr(name1,'/');
3078 name2 = strrchr(name2,'/');
3080 if (!name1 || !name2) return(False);
3082 fstrcpy(root1,name1);
3083 fstrcpy(root2,name2);
3084 p = strrchr(root1,'.');
3085 if (p) {
3086 *p = 0;
3087 fstrcpy(ext1,p+1);
3088 } else {
3089 fstrcpy(ext1,"");
3091 p = strrchr(root2,'.');
3092 if (p) {
3093 *p = 0;
3094 fstrcpy(ext2,p+1);
3095 } else {
3096 fstrcpy(ext2,"");
3099 p = root1;
3100 p2 = root2;
3101 while (*p2) {
3102 if (*p2 == '?') {
3103 *p2 = *p;
3104 p2++;
3105 } else {
3106 p2++;
3108 if (*p) p++;
3111 p = ext1;
3112 p2 = ext2;
3113 while (*p2) {
3114 if (*p2 == '?') {
3115 *p2 = *p;
3116 p2++;
3117 } else {
3118 p2++;
3120 if (*p) p++;
3123 pstrcpy(name2,root2);
3124 if (ext2[0]) {
3125 pstrcat(name2,".");
3126 pstrcat(name2,ext2);
3129 return(True);
3132 /*******************************************************************
3133 check if a user is allowed to rename a file
3134 ********************************************************************/
3135 static BOOL can_rename(char *fname,connection_struct *conn)
3137 SMB_STRUCT_STAT sbuf;
3139 if (!CAN_WRITE(conn)) return(False);
3141 if (dos_lstat(fname,&sbuf) != 0) return(False);
3142 if (!check_file_sharing(conn,fname,True)) return(False);
3144 return(True);
3147 /****************************************************************************
3148 The guts of the rename command, split out so it may be called by the NT SMB
3149 code.
3150 ****************************************************************************/
3151 int rename_internals(connection_struct *conn,
3152 char *inbuf, char *outbuf, char *name,
3153 char *newname, BOOL replace_if_exists)
3155 pstring directory;
3156 pstring mask;
3157 pstring newname_last_component;
3158 char *p;
3159 BOOL has_wild;
3160 BOOL bad_path1 = False;
3161 BOOL bad_path2 = False;
3162 int count=0;
3163 int error = ERRnoaccess;
3164 BOOL exists=False;
3166 *directory = *mask = 0;
3168 unix_convert(name,conn,0,&bad_path1,NULL);
3169 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3172 * Split the old name into directory and last component
3173 * strings. Note that unix_convert may have stripped off a
3174 * leading ./ from both name and newname if the rename is
3175 * at the root of the share. We need to make sure either both
3176 * name and newname contain a / character or neither of them do
3177 * as this is checked in resolve_wildcards().
3180 p = strrchr(name,'/');
3181 if (!p) {
3182 pstrcpy(directory,".");
3183 pstrcpy(mask,name);
3184 } else {
3185 *p = 0;
3186 pstrcpy(directory,name);
3187 pstrcpy(mask,p+1);
3188 *p = '/'; /* Replace needed for exceptional test below. */
3191 if (is_mangled(mask))
3192 check_mangled_cache( mask );
3194 has_wild = strchr(mask,'*') || strchr(mask,'?');
3196 if (!has_wild) {
3198 * No wildcards - just process the one file.
3200 BOOL is_short_name = is_8_3(name, True);
3202 /* Add a terminating '/' to the directory name. */
3203 pstrcat(directory,"/");
3204 pstrcat(directory,mask);
3206 /* Ensure newname contains a '/' also */
3207 if(strrchr(newname,'/') == 0) {
3208 pstring tmpstr;
3210 pstrcpy(tmpstr, "./");
3211 pstrcat(tmpstr, newname);
3212 pstrcpy(newname, tmpstr);
3215 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",
3216 case_sensitive, case_preserve, short_case_preserve, directory,
3217 newname, newname_last_component, is_short_name));
3220 * Check for special case with case preserving and not
3221 * case sensitive, if directory and newname are identical,
3222 * and the old last component differs from the original
3223 * last component only by case, then we should allow
3224 * the rename (user is trying to change the case of the
3225 * filename).
3227 if((case_sensitive == False) &&
3228 (((case_preserve == True) &&
3229 (is_short_name == False)) ||
3230 ((short_case_preserve == True) &&
3231 (is_short_name == True))) &&
3232 strcsequal(directory, newname)) {
3233 pstring newname_modified_last_component;
3236 * Get the last component of the modified name.
3237 * Note that we guarantee that newname contains a '/'
3238 * character above.
3240 p = strrchr(newname,'/');
3241 pstrcpy(newname_modified_last_component,p+1);
3243 if(strcsequal(newname_modified_last_component,
3244 newname_last_component) == False) {
3246 * Replace the modified last component with
3247 * the original.
3249 pstrcpy(p+1, newname_last_component);
3253 if(replace_if_exists) {
3255 * NT SMB specific flag - rename can overwrite
3256 * file with the same name so don't check for
3257 * file_exist().
3259 if(resolve_wildcards(directory,newname) &&
3260 can_rename(directory,conn) &&
3261 !dos_rename(directory,newname))
3262 count++;
3263 } else {
3264 if (resolve_wildcards(directory,newname) &&
3265 can_rename(directory,conn) &&
3266 !file_exist(newname,NULL) &&
3267 !dos_rename(directory,newname))
3268 count++;
3271 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3272 directory,newname));
3274 if (!count) exists = file_exist(directory,NULL);
3275 if (!count && exists && file_exist(newname,NULL)) {
3276 exists = True;
3277 error = ERRrename;
3279 } else {
3281 * Wildcards - process each file that matches.
3283 void *dirptr = NULL;
3284 char *dname;
3285 pstring destname;
3287 if (check_name(directory,conn))
3288 dirptr = OpenDir(conn, directory, True);
3290 if (dirptr) {
3291 error = ERRbadfile;
3293 if (strequal(mask,"????????.???"))
3294 pstrcpy(mask,"*");
3296 while ((dname = ReadDirName(dirptr))) {
3297 pstring fname;
3298 pstrcpy(fname,dname);
3300 if(!mask_match(fname, mask, case_sensitive, False))
3301 continue;
3303 error = ERRnoaccess;
3304 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3305 if (!can_rename(fname,conn)) {
3306 DEBUG(6,("rename %s refused\n", fname));
3307 continue;
3309 pstrcpy(destname,newname);
3311 if (!resolve_wildcards(fname,destname)) {
3312 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3313 continue;
3316 if (!replace_if_exists && file_exist(destname,NULL)) {
3317 DEBUG(6,("file_exist %s\n", destname));
3318 error = 183;
3319 continue;
3322 if (!dos_rename(fname,destname))
3323 count++;
3324 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3326 CloseDir(dirptr);
3330 if (count == 0) {
3331 if (exists)
3332 return(ERROR(ERRDOS,error));
3333 else {
3334 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3335 unix_ERR_class = ERRDOS;
3336 unix_ERR_code = ERRbadpath;
3338 return(UNIXERROR(ERRDOS,error));
3342 return 0;
3345 /****************************************************************************
3346 Reply to a mv.
3347 ****************************************************************************/
3349 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3351 int outsize = 0;
3352 pstring name;
3353 pstring newname;
3355 pstrcpy(name,smb_buf(inbuf) + 1);
3356 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3358 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3360 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3361 if(outsize == 0)
3362 outsize = set_message(outbuf,0,0,True);
3364 return(outsize);
3367 /*******************************************************************
3368 copy a file as part of a reply_copy
3369 ******************************************************************/
3371 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3372 int count,BOOL target_is_directory)
3374 int Access,action;
3375 SMB_STRUCT_STAT st;
3376 int ret=-1;
3377 files_struct *fsp1,*fsp2;
3378 pstring dest;
3380 pstrcpy(dest,dest1);
3381 if (target_is_directory) {
3382 char *p = strrchr(src,'/');
3383 if (p)
3384 p++;
3385 else
3386 p = src;
3387 pstrcat(dest,"/");
3388 pstrcat(dest,p);
3391 if (!file_exist(src,&st))
3392 return(False);
3394 fsp1 = file_new();
3395 if (!fsp1)
3396 return(False);
3398 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3399 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3401 if (!fsp1->open) {
3402 file_free(fsp1);
3403 return(False);
3406 if (!target_is_directory && count)
3407 ofun = 1;
3409 fsp2 = file_new();
3410 if (!fsp2) {
3411 close_file(fsp1,False);
3412 return(False);
3414 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3415 ofun,st.st_mode,0,&Access,&action);
3417 if (!fsp2->open) {
3418 close_file(fsp1,False);
3419 file_free(fsp2);
3420 return(False);
3423 if ((ofun&3) == 1) {
3424 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3425 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3426 strerror(errno) ));
3428 * Stop the copy from occurring.
3430 ret = -1;
3431 st.st_size = 0;
3435 if (st.st_size)
3436 ret = transfer_file(fsp1->fd_ptr->fd,
3437 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3439 close_file(fsp1,False);
3440 close_file(fsp2,False);
3442 return(ret == st.st_size);
3447 /****************************************************************************
3448 reply to a file copy.
3449 ****************************************************************************/
3450 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3452 int outsize = 0;
3453 pstring name;
3454 pstring directory;
3455 pstring mask,newname;
3456 char *p;
3457 int count=0;
3458 int error = ERRnoaccess;
3459 BOOL has_wild;
3460 BOOL exists=False;
3461 int tid2 = SVAL(inbuf,smb_vwv0);
3462 int ofun = SVAL(inbuf,smb_vwv1);
3463 int flags = SVAL(inbuf,smb_vwv2);
3464 BOOL target_is_directory=False;
3465 BOOL bad_path1 = False;
3466 BOOL bad_path2 = False;
3468 *directory = *mask = 0;
3470 pstrcpy(name,smb_buf(inbuf));
3471 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3473 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3475 if (tid2 != conn->cnum) {
3476 /* can't currently handle inter share copies XXXX */
3477 DEBUG(3,("Rejecting inter-share copy\n"));
3478 return(ERROR(ERRSRV,ERRinvdevice));
3481 unix_convert(name,conn,0,&bad_path1,NULL);
3482 unix_convert(newname,conn,0,&bad_path2,NULL);
3484 target_is_directory = directory_exist(newname,NULL);
3486 if ((flags&1) && target_is_directory) {
3487 return(ERROR(ERRDOS,ERRbadfile));
3490 if ((flags&2) && !target_is_directory) {
3491 return(ERROR(ERRDOS,ERRbadpath));
3494 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3495 /* wants a tree copy! XXXX */
3496 DEBUG(3,("Rejecting tree copy\n"));
3497 return(ERROR(ERRSRV,ERRerror));
3500 p = strrchr(name,'/');
3501 if (!p) {
3502 pstrcpy(directory,"./");
3503 pstrcpy(mask,name);
3504 } else {
3505 *p = 0;
3506 pstrcpy(directory,name);
3507 pstrcpy(mask,p+1);
3510 if (is_mangled(mask))
3511 check_mangled_cache( mask );
3513 has_wild = strchr(mask,'*') || strchr(mask,'?');
3515 if (!has_wild) {
3516 pstrcat(directory,"/");
3517 pstrcat(directory,mask);
3518 if (resolve_wildcards(directory,newname) &&
3519 copy_file(directory,newname,conn,ofun,
3520 count,target_is_directory)) count++;
3521 if (!count) exists = file_exist(directory,NULL);
3522 } else {
3523 void *dirptr = NULL;
3524 char *dname;
3525 pstring destname;
3527 if (check_name(directory,conn))
3528 dirptr = OpenDir(conn, directory, True);
3530 if (dirptr)
3532 error = ERRbadfile;
3534 if (strequal(mask,"????????.???"))
3535 pstrcpy(mask,"*");
3537 while ((dname = ReadDirName(dirptr)))
3539 pstring fname;
3540 pstrcpy(fname,dname);
3542 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3544 error = ERRnoaccess;
3545 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3546 pstrcpy(destname,newname);
3547 if (resolve_wildcards(fname,destname) &&
3548 copy_file(directory,newname,conn,ofun,
3549 count,target_is_directory)) count++;
3550 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3552 CloseDir(dirptr);
3556 if (count == 0) {
3557 if (exists)
3558 return(ERROR(ERRDOS,error));
3559 else
3561 if((errno == ENOENT) && (bad_path1 || bad_path2))
3563 unix_ERR_class = ERRDOS;
3564 unix_ERR_code = ERRbadpath;
3566 return(UNIXERROR(ERRDOS,error));
3570 outsize = set_message(outbuf,1,0,True);
3571 SSVAL(outbuf,smb_vwv0,count);
3573 return(outsize);
3576 /****************************************************************************
3577 reply to a setdir
3578 ****************************************************************************/
3579 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3581 int snum;
3582 int outsize = 0;
3583 BOOL ok = False;
3584 pstring newdir;
3586 snum = SNUM(conn);
3587 if (!CAN_SETDIR(snum))
3588 return(ERROR(ERRDOS,ERRnoaccess));
3590 pstrcpy(newdir,smb_buf(inbuf) + 1);
3591 strlower(newdir);
3593 if (strlen(newdir) == 0) {
3594 ok = True;
3595 } else {
3596 ok = directory_exist(newdir,NULL);
3597 if (ok) {
3598 string_set(&conn->connectpath,newdir);
3602 if (!ok)
3603 return(ERROR(ERRDOS,ERRbadpath));
3605 outsize = set_message(outbuf,0,0,True);
3606 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3608 DEBUG(3,("setdir %s\n", newdir));
3610 return(outsize);
3613 /****************************************************************************
3614 reply to a lockingX request
3615 ****************************************************************************/
3616 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3618 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3619 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3620 #if 0
3621 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3622 #endif
3623 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3624 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3625 SMB_OFF_T count = 0, offset = 0;
3626 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3627 int i;
3628 char *data;
3629 uint32 ecode=0, dummy2;
3630 int eclass=0, dummy1;
3631 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3632 CHECK_FSP(fsp,conn);
3633 CHECK_ERROR(fsp);
3635 data = smb_buf(inbuf);
3637 /* Check if this is an oplock break on a file
3638 we have granted an oplock on.
3640 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3642 int token;
3643 SMB_DEV_T dev = fsp->fd_ptr->dev;
3644 SMB_INO_T inode = fsp->fd_ptr->inode;
3646 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3647 fsp->fnum));
3649 * Make sure we have granted an oplock on this file.
3651 if(!fsp->granted_oplock)
3653 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3654 no oplock granted on this file.\n", fsp->fnum));
3655 return ERROR(ERRDOS,ERRlock);
3658 /* Remove the oplock flag from the sharemode. */
3659 lock_share_entry(fsp->conn, dev, inode, &token);
3660 if(remove_share_oplock(token, fsp)==False) {
3662 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3663 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3665 unlock_share_entry(fsp->conn, dev, inode, token);
3666 } else {
3667 unlock_share_entry(fsp->conn, dev, inode, token);
3669 /* Clear the granted flag and return. */
3670 fsp->granted_oplock = False;
3673 /* if this is a pure oplock break request then don't send a reply */
3674 if (num_locks == 0 && num_ulocks == 0)
3676 /* Sanity check - ensure a pure oplock break is not a
3677 chained request. */
3678 if(CVAL(inbuf,smb_vwv0) != 0xff)
3679 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3680 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3681 return -1;
3685 /* Data now points at the beginning of the list
3686 of smb_unlkrng structs */
3687 for(i = 0; i < (int)num_ulocks; i++) {
3688 if(!large_file_format) {
3689 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3690 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3692 #ifdef LARGE_SMB_OFF_T
3693 else {
3694 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3695 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3696 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3697 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3699 #endif /* LARGE_SMB_OFF_T */
3701 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3702 (double)offset, (double)count, fsp->fsp_name ));
3704 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3705 return ERROR(eclass,ecode);
3708 /* Setup the timeout in seconds. */
3709 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3711 /* Now do any requested locks */
3712 data += ((large_file_format ? 20 : 10)*num_ulocks);
3714 /* Data now points at the beginning of the list
3715 of smb_lkrng structs */
3717 for(i = 0; i < (int)num_locks; i++) {
3718 if(!large_file_format) {
3719 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3720 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3722 #ifdef LARGE_SMB_OFF_T
3723 else {
3724 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3725 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3726 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3727 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3729 #endif /* LARGE_SMB_OFF_T */
3731 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3732 (double)offset, (double)count, fsp->fsp_name ));
3734 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3735 &eclass, &ecode)) {
3736 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3738 * A blocking lock was requested. Package up
3739 * this smb into a queued request and push it
3740 * onto the blocking lock queue.
3742 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3743 return -1;
3745 break;
3749 /* If any of the above locks failed, then we must unlock
3750 all of the previous locks (X/Open spec). */
3751 if(i != num_locks && num_locks != 0) {
3752 for(; i >= 0; i--) {
3753 if(!large_file_format) {
3754 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3755 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3757 #ifdef LARGE_SMB_OFF_T
3758 else {
3759 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3760 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3761 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3762 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3764 #endif /* LARGE_SMB_OFF_T */
3766 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3768 return ERROR(eclass,ecode);
3771 set_message(outbuf,2,0,True);
3773 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3774 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3776 return chain_reply(inbuf,outbuf,length,bufsize);
3780 /****************************************************************************
3781 reply to a SMBreadbmpx (read block multiplex) request
3782 ****************************************************************************/
3783 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3785 ssize_t nread = -1;
3786 ssize_t total_read;
3787 char *data;
3788 SMB_OFF_T startpos;
3789 int outsize;
3790 size_t maxcount;
3791 int max_per_packet;
3792 size_t tcount;
3793 int pad;
3794 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3796 /* this function doesn't seem to work - disable by default */
3797 if (!lp_readbmpx())
3798 return(ERROR(ERRSRV,ERRuseSTD));
3800 outsize = set_message(outbuf,8,0,True);
3802 CHECK_FSP(fsp,conn);
3803 CHECK_READ(fsp);
3804 CHECK_ERROR(fsp);
3806 startpos = IVAL(inbuf,smb_vwv1);
3807 maxcount = SVAL(inbuf,smb_vwv3);
3809 data = smb_buf(outbuf);
3810 pad = ((long)data)%4;
3811 if (pad) pad = 4 - pad;
3812 data += pad;
3814 max_per_packet = bufsize-(outsize+pad);
3815 tcount = maxcount;
3816 total_read = 0;
3818 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3819 return(ERROR(ERRDOS,ERRlock));
3823 size_t N = MIN(max_per_packet,tcount-total_read);
3825 nread = read_file(fsp,data,startpos,N);
3827 if (nread <= 0) nread = 0;
3829 if (nread < (ssize_t)N)
3830 tcount = total_read + nread;
3832 set_message(outbuf,8,nread,False);
3833 SIVAL(outbuf,smb_vwv0,startpos);
3834 SSVAL(outbuf,smb_vwv2,tcount);
3835 SSVAL(outbuf,smb_vwv6,nread);
3836 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3838 send_smb(Client,outbuf);
3840 total_read += nread;
3841 startpos += nread;
3843 while (total_read < (ssize_t)tcount);
3845 return(-1);
3848 /****************************************************************************
3849 reply to a SMBwritebmpx (write block multiplex primary) request
3850 ****************************************************************************/
3851 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3853 size_t numtowrite;
3854 ssize_t nwritten = -1;
3855 int outsize = 0;
3856 SMB_OFF_T startpos;
3857 size_t tcount;
3858 BOOL write_through;
3859 int smb_doff;
3860 char *data;
3861 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3863 CHECK_FSP(fsp,conn);
3864 CHECK_WRITE(fsp);
3865 CHECK_ERROR(fsp);
3867 tcount = SVAL(inbuf,smb_vwv1);
3868 startpos = IVAL(inbuf,smb_vwv3);
3869 write_through = BITSETW(inbuf+smb_vwv7,0);
3870 numtowrite = SVAL(inbuf,smb_vwv10);
3871 smb_doff = SVAL(inbuf,smb_vwv11);
3873 data = smb_base(inbuf) + smb_doff;
3875 /* If this fails we need to send an SMBwriteC response,
3876 not an SMBwritebmpx - set this up now so we don't forget */
3877 CVAL(outbuf,smb_com) = SMBwritec;
3879 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3880 return(ERROR(ERRDOS,ERRlock));
3882 if(seek_file(fsp,startpos) == -1)
3883 return(UNIXERROR(ERRDOS,ERRnoaccess));
3885 nwritten = write_file(fsp,data,numtowrite);
3887 if(lp_syncalways(SNUM(conn)) || write_through)
3888 sync_file(conn,fsp);
3890 if(nwritten < (ssize_t)numtowrite)
3891 return(UNIXERROR(ERRHRD,ERRdiskfull));
3893 /* If the maximum to be written to this file
3894 is greater than what we just wrote then set
3895 up a secondary struct to be attached to this
3896 fd, we will use this to cache error messages etc. */
3897 if((ssize_t)tcount > nwritten)
3899 write_bmpx_struct *wbms;
3900 if(fsp->wbmpx_ptr != NULL)
3901 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3902 else
3903 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3904 if(!wbms)
3906 DEBUG(0,("Out of memory in reply_readmpx\n"));
3907 return(ERROR(ERRSRV,ERRnoresource));
3909 wbms->wr_mode = write_through;
3910 wbms->wr_discard = False; /* No errors yet */
3911 wbms->wr_total_written = nwritten;
3912 wbms->wr_errclass = 0;
3913 wbms->wr_error = 0;
3914 fsp->wbmpx_ptr = wbms;
3917 /* We are returning successfully, set the message type back to
3918 SMBwritebmpx */
3919 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3921 outsize = set_message(outbuf,1,0,True);
3923 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3925 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3926 fsp->fnum, numtowrite, nwritten ) );
3928 if (write_through && tcount==nwritten) {
3929 /* we need to send both a primary and a secondary response */
3930 smb_setlen(outbuf,outsize - 4);
3931 send_smb(Client,outbuf);
3933 /* now the secondary */
3934 outsize = set_message(outbuf,1,0,True);
3935 CVAL(outbuf,smb_com) = SMBwritec;
3936 SSVAL(outbuf,smb_vwv0,nwritten);
3939 return(outsize);
3943 /****************************************************************************
3944 reply to a SMBwritebs (write block multiplex secondary) request
3945 ****************************************************************************/
3946 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3948 size_t numtowrite;
3949 ssize_t nwritten = -1;
3950 int outsize = 0;
3951 SMB_OFF_T startpos;
3952 size_t tcount;
3953 BOOL write_through;
3954 int smb_doff;
3955 char *data;
3956 write_bmpx_struct *wbms;
3957 BOOL send_response = False;
3958 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3960 CHECK_FSP(fsp,conn);
3961 CHECK_WRITE(fsp);
3963 tcount = SVAL(inbuf,smb_vwv1);
3964 startpos = IVAL(inbuf,smb_vwv2);
3965 numtowrite = SVAL(inbuf,smb_vwv6);
3966 smb_doff = SVAL(inbuf,smb_vwv7);
3968 data = smb_base(inbuf) + smb_doff;
3970 /* We need to send an SMBwriteC response, not an SMBwritebs */
3971 CVAL(outbuf,smb_com) = SMBwritec;
3973 /* This fd should have an auxiliary struct attached,
3974 check that it does */
3975 wbms = fsp->wbmpx_ptr;
3976 if(!wbms) return(-1);
3978 /* If write through is set we can return errors, else we must
3979 cache them */
3980 write_through = wbms->wr_mode;
3982 /* Check for an earlier error */
3983 if(wbms->wr_discard)
3984 return -1; /* Just discard the packet */
3986 if(seek_file(fsp,startpos) == -1)
3988 if(write_through)
3990 /* We are returning an error - we can delete the aux struct */
3991 if (wbms) free((char *)wbms);
3992 fsp->wbmpx_ptr = NULL;
3993 return(UNIXERROR(ERRDOS,ERRnoaccess));
3995 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
3998 nwritten = write_file(fsp,data,numtowrite);
4000 if(lp_syncalways(SNUM(conn)) || write_through)
4001 sync_file(conn,fsp);
4003 if (nwritten < (ssize_t)numtowrite)
4005 if(write_through)
4007 /* We are returning an error - we can delete the aux struct */
4008 if (wbms) free((char *)wbms);
4009 fsp->wbmpx_ptr = NULL;
4010 return(ERROR(ERRHRD,ERRdiskfull));
4012 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4015 /* Increment the total written, if this matches tcount
4016 we can discard the auxiliary struct (hurrah !) and return a writeC */
4017 wbms->wr_total_written += nwritten;
4018 if(wbms->wr_total_written >= tcount)
4020 if (write_through)
4022 outsize = set_message(outbuf,1,0,True);
4023 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4024 send_response = True;
4027 free((char *)wbms);
4028 fsp->wbmpx_ptr = NULL;
4031 if(send_response)
4032 return(outsize);
4034 return(-1);
4038 /****************************************************************************
4039 reply to a SMBsetattrE
4040 ****************************************************************************/
4041 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4043 struct utimbuf unix_times;
4044 int outsize = 0;
4045 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4047 outsize = set_message(outbuf,0,0,True);
4049 CHECK_FSP(fsp,conn);
4050 CHECK_ERROR(fsp);
4052 /* Convert the DOS times into unix times. Ignore create
4053 time as UNIX can't set this.
4055 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4056 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4059 * Patch from Ray Frush <frush@engr.colostate.edu>
4060 * Sometimes times are sent as zero - ignore them.
4063 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4065 /* Ignore request */
4066 if( DEBUGLVL( 3 ) )
4068 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4069 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4071 return(outsize);
4073 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4075 /* set modify time = to access time if modify time was 0 */
4076 unix_times.modtime = unix_times.actime;
4079 /* Set the date on this file */
4080 if(file_utime(conn, fsp->fsp_name, &unix_times))
4081 return(ERROR(ERRDOS,ERRnoaccess));
4083 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4084 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4086 return(outsize);
4090 /****************************************************************************
4091 reply to a SMBgetattrE
4092 ****************************************************************************/
4093 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4095 SMB_STRUCT_STAT sbuf;
4096 int outsize = 0;
4097 int mode;
4098 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4100 outsize = set_message(outbuf,11,0,True);
4102 CHECK_FSP(fsp,conn);
4103 CHECK_ERROR(fsp);
4105 /* Do an fstat on this file */
4106 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4107 return(UNIXERROR(ERRDOS,ERRnoaccess));
4109 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4111 /* Convert the times into dos times. Set create
4112 date to be last modify date as UNIX doesn't save
4113 this */
4114 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4115 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4116 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4117 if (mode & aDIR)
4119 SIVAL(outbuf,smb_vwv6,0);
4120 SIVAL(outbuf,smb_vwv8,0);
4122 else
4124 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4125 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
4127 SSVAL(outbuf,smb_vwv10, mode);
4129 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4131 return(outsize);