Makefile.in: Fixed bug with continuation line causing proto to fail.
[Samba/gebeck_regimport.git] / source / smbd / reply.c
blob63bbcbcdba5aad0e8b32988faf546e574be5cd1f
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, (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));
451 /****************************************************************************
452 reply to a session setup command
453 ****************************************************************************/
454 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
456 uint16 sess_vuid;
457 int gid;
458 int uid;
459 int smb_bufsize;
460 int smb_apasslen = 0;
461 pstring smb_apasswd;
462 int smb_ntpasslen = 0;
463 pstring smb_ntpasswd;
464 BOOL valid_nt_password = False;
465 pstring user;
466 pstring orig_user;
467 BOOL guest=False;
468 static BOOL done_sesssetup = False;
469 BOOL doencrypt = SMBENCRYPT();
470 char *domain = "";
472 *smb_apasswd = 0;
473 *smb_ntpasswd = 0;
475 smb_bufsize = SVAL(inbuf,smb_vwv2);
477 if (Protocol < PROTOCOL_NT1) {
478 smb_apasslen = SVAL(inbuf,smb_vwv7);
479 if (smb_apasslen > MAX_PASS_LEN)
481 overflow_attack(smb_apasslen);
484 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
485 smb_apasswd[smb_apasslen] = 0;
486 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
488 if (!doencrypt && (lp_security() != SEC_SERVER)) {
489 smb_apasslen = strlen(smb_apasswd);
491 } else {
492 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
493 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
494 enum remote_arch_types ra_type = get_remote_arch();
495 char *p = smb_buf(inbuf);
497 global_client_caps = IVAL(inbuf,smb_vwv11);
499 /* client_caps is used as final determination if client is NT or Win95.
500 This is needed to return the correct error codes in some
501 circumstances.
504 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
506 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
507 set_remote_arch( RA_WINNT);
508 else
509 set_remote_arch( RA_WIN95);
512 if (passlen1 != 24 && passlen2 != 24)
513 doencrypt = False;
515 if (passlen1 > MAX_PASS_LEN) {
516 overflow_attack(passlen1);
519 passlen1 = MIN(passlen1, MAX_PASS_LEN);
520 passlen2 = MIN(passlen2, MAX_PASS_LEN);
522 if(!doencrypt) {
523 /* both Win95 and WinNT stuff up the password lengths for
524 non-encrypting systems. Uggh.
526 if passlen1==24 its a win95 system, and its setting the
527 password length incorrectly. Luckily it still works with the
528 default code because Win95 will null terminate the password
529 anyway
531 if passlen1>0 and passlen2>0 then maybe its a NT box and its
532 setting passlen2 to some random value which really stuffs
533 things up. we need to fix that one. */
535 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
536 passlen2 = 0;
539 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
540 /* Save the lanman2 password and the NT md4 password. */
541 smb_apasslen = passlen1;
542 memcpy(smb_apasswd,p,smb_apasslen);
543 smb_apasswd[smb_apasslen] = 0;
544 smb_ntpasslen = passlen2;
545 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
546 smb_ntpasswd[smb_ntpasslen] = 0;
547 } else {
548 /* we use the first password that they gave */
549 smb_apasslen = passlen1;
550 StrnCpy(smb_apasswd,p,smb_apasslen);
552 /* trim the password */
553 smb_apasslen = strlen(smb_apasswd);
555 /* wfwg sometimes uses a space instead of a null */
556 if (strequal(smb_apasswd," ")) {
557 smb_apasslen = 0;
558 *smb_apasswd = 0;
562 p += passlen1 + passlen2;
563 fstrcpy(user,p); p = skip_string(p,1);
564 domain = p;
566 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
567 domain,skip_string(p,1),skip_string(p,2)));
571 DEBUG(3,("sesssetupX:name=[%s]\n",user));
573 /* If name ends in $ then I think it's asking about whether a */
574 /* computer with that name (minus the $) has access. For now */
575 /* say yes to everything ending in $. */
576 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
578 return session_trust_account(conn, inbuf, outbuf, user,
579 smb_apasswd, smb_apasslen,
580 smb_ntpasswd, smb_ntpasslen);
583 /* If no username is sent use the guest account */
584 if (!*user)
586 pstrcpy(user,lp_guestaccount(-1));
587 /* If no user and no password then set guest flag. */
588 if( *smb_apasswd == 0)
589 guest = True;
592 strlower(user);
595 * In share level security, only overwrite sesssetup_use if
596 * it's a non null-session share. Helps keep %U and %G
597 * working.
600 if((lp_security() != SEC_SHARE) || *user)
601 pstrcpy(sesssetup_user,user);
603 reload_services(True);
606 * Save the username before mapping. We will use
607 * the original username sent to us for security=server
608 * and security=domain checking.
611 pstrcpy( orig_user, user);
614 * Pass the user through the NT -> unix user mapping
615 * function.
618 (void)map_username(user);
621 * Do any UNIX username case mangling.
623 (void)Get_Pwnam( user, True);
625 add_session_user(user);
628 * Check if the given username was the guest user with no password.
631 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
632 guest = True;
634 if (!guest && !(lp_security() == SEC_SERVER &&
635 /* Check with orig_user for security=server and
636 security=domain. */
637 server_validate(orig_user, domain,
638 smb_apasswd, smb_apasslen,
639 smb_ntpasswd, smb_ntpasslen)) &&
640 !(lp_security() == SEC_DOMAIN &&
641 domain_client_validate(orig_user, domain,
642 smb_apasswd, smb_apasslen,
643 smb_ntpasswd, smb_ntpasslen)) &&
644 !check_hosts_equiv(user)
648 /* now check if it's a valid username/password */
649 /* If an NT password was supplied try and validate with that
650 first. This is superior as the passwords are mixed case
651 128 length unicode */
652 if(smb_ntpasslen)
654 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
655 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
656 else
657 valid_nt_password = True;
659 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
661 if (lp_security() >= SEC_USER) {
662 #if (GUEST_SESSSETUP == 0)
663 return(ERROR(ERRSRV,ERRbadpw));
664 #endif
665 #if (GUEST_SESSSETUP == 1)
666 if (Get_Pwnam(user,True))
667 return(ERROR(ERRSRV,ERRbadpw));
668 #endif
670 if (*smb_apasswd || !Get_Pwnam(user,True))
671 pstrcpy(user,lp_guestaccount(-1));
672 DEBUG(3,("Registered username %s for guest access\n",user));
673 guest = True;
677 if (!Get_Pwnam(user,True)) {
678 DEBUG(3,("No such user %s - using guest account\n",user));
679 pstrcpy(user,lp_guestaccount(-1));
680 guest = True;
683 if (!strequal(user,lp_guestaccount(-1)) &&
684 lp_servicenumber(user) < 0)
686 int homes = lp_servicenumber(HOMES_NAME);
687 char *home = get_home_dir(user);
688 if (homes >= 0 && home)
689 lp_add_home(user,homes,home);
693 /* it's ok - setup a reply */
694 if (Protocol < PROTOCOL_NT1) {
695 set_message(outbuf,3,0,True);
696 } else {
697 char *p;
698 set_message(outbuf,3,3,True);
699 p = smb_buf(outbuf);
700 pstrcpy(p,"Unix"); p = skip_string(p,1);
701 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
702 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
703 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
704 /* perhaps grab OS version here?? */
707 /* Set the correct uid in the outgoing and incoming packets
708 We will use this on future requests to determine which
709 user we should become.
712 struct passwd *pw = Get_Pwnam(user,False);
713 if (!pw) {
714 DEBUG(1,("Username %s is invalid on this system\n",user));
715 return(ERROR(ERRSRV,ERRbadpw));
717 gid = pw->pw_gid;
718 uid = pw->pw_uid;
721 if (guest)
722 SSVAL(outbuf,smb_vwv2,1);
724 /* register the name and uid as being validated, so further connections
725 to a uid can get through without a password, on the same VC */
726 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
728 SSVAL(outbuf,smb_uid,sess_vuid);
729 SSVAL(inbuf,smb_uid,sess_vuid);
731 if (!done_sesssetup)
732 max_send = MIN(max_send,smb_bufsize);
734 DEBUG(6,("Client requested max send size of %d\n", max_send));
736 done_sesssetup = True;
738 return chain_reply(inbuf,outbuf,length,bufsize);
742 /****************************************************************************
743 reply to a chkpth
744 ****************************************************************************/
745 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
747 int outsize = 0;
748 int mode;
749 pstring name;
750 BOOL ok = False;
751 BOOL bad_path = False;
752 SMB_STRUCT_STAT st;
754 pstrcpy(name,smb_buf(inbuf) + 1);
755 unix_convert(name,conn,0,&bad_path,&st);
757 mode = SVAL(inbuf,smb_vwv0);
759 if (check_name(name,conn)) {
760 if(VALID_STAT(st))
761 ok = S_ISDIR(st.st_mode);
762 else
763 ok = directory_exist(name,NULL);
766 if (!ok)
768 /* We special case this - as when a Windows machine
769 is parsing a path is steps through the components
770 one at a time - if a component fails it expects
771 ERRbadpath, not ERRbadfile.
773 if(errno == ENOENT)
775 unix_ERR_class = ERRDOS;
776 unix_ERR_code = ERRbadpath;
779 #if 0
780 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
781 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
782 (get_remote_arch() == RA_WINNT))
784 unix_ERR_class = ERRDOS;
785 unix_ERR_code = ERRbaddirectory;
787 #endif
789 return(UNIXERROR(ERRDOS,ERRbadpath));
792 outsize = set_message(outbuf,0,0,True);
794 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
796 return(outsize);
800 /****************************************************************************
801 reply to a getatr
802 ****************************************************************************/
803 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
805 pstring fname;
806 int outsize = 0;
807 SMB_STRUCT_STAT sbuf;
808 BOOL ok = False;
809 int mode=0;
810 SMB_OFF_T size=0;
811 time_t mtime=0;
812 BOOL bad_path = False;
814 pstrcpy(fname,smb_buf(inbuf) + 1);
815 unix_convert(fname,conn,0,&bad_path,&sbuf);
817 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
818 under WfWg - weird! */
819 if (! (*fname))
821 mode = aHIDDEN | aDIR;
822 if (!CAN_WRITE(conn)) mode |= aRONLY;
823 size = 0;
824 mtime = 0;
825 ok = True;
827 else
828 if (check_name(fname,conn))
830 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
832 mode = dos_mode(conn,fname,&sbuf);
833 size = sbuf.st_size;
834 mtime = sbuf.st_mtime;
835 if (mode & aDIR)
836 size = 0;
837 ok = True;
839 else
840 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
843 if (!ok)
845 if((errno == ENOENT) && bad_path)
847 unix_ERR_class = ERRDOS;
848 unix_ERR_code = ERRbadpath;
851 return(UNIXERROR(ERRDOS,ERRbadfile));
854 outsize = set_message(outbuf,10,0,True);
856 SSVAL(outbuf,smb_vwv0,mode);
857 if(lp_dos_filetime_resolution(SNUM(conn)) )
858 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
859 else
860 put_dos_date3(outbuf,smb_vwv1,mtime);
861 SIVAL(outbuf,smb_vwv3,(uint32)size);
863 if (Protocol >= PROTOCOL_NT1) {
864 char *p = strrchr(fname,'/');
865 uint16 flg2 = SVAL(outbuf,smb_flg2);
866 if (!p) p = fname;
867 if (!is_8_3(fname, True))
868 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
871 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
873 return(outsize);
877 /****************************************************************************
878 reply to a setatr
879 ****************************************************************************/
880 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
882 pstring fname;
883 int outsize = 0;
884 BOOL ok=False;
885 int mode;
886 time_t mtime;
887 SMB_STRUCT_STAT st;
888 BOOL bad_path = False;
890 pstrcpy(fname,smb_buf(inbuf) + 1);
891 unix_convert(fname,conn,0,&bad_path,&st);
893 mode = SVAL(inbuf,smb_vwv0);
894 mtime = make_unix_date3(inbuf+smb_vwv1);
896 if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL))
897 mode |= aDIR;
898 if (check_name(fname,conn))
899 ok = (file_chmod(conn,fname,mode,NULL) == 0);
900 if (ok)
901 ok = set_filetime(conn,fname,mtime);
903 if (!ok)
905 if((errno == ENOENT) && bad_path)
907 unix_ERR_class = ERRDOS;
908 unix_ERR_code = ERRbadpath;
911 return(UNIXERROR(ERRDOS,ERRnoaccess));
914 outsize = set_message(outbuf,0,0,True);
916 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
918 return(outsize);
922 /****************************************************************************
923 reply to a dskattr
924 ****************************************************************************/
925 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
927 int outsize = 0;
928 SMB_BIG_UINT dfree,dsize,bsize;
930 sys_disk_free(".",&bsize,&dfree,&dsize);
932 outsize = set_message(outbuf,5,0,True);
934 SSVAL(outbuf,smb_vwv0,dsize);
935 SSVAL(outbuf,smb_vwv1,bsize/512);
936 SSVAL(outbuf,smb_vwv2,512);
937 SSVAL(outbuf,smb_vwv3,dfree);
939 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
941 return(outsize);
945 /****************************************************************************
946 reply to a search
947 Can be called from SMBsearch, SMBffirst or SMBfunique.
948 ****************************************************************************/
949 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
951 pstring mask;
952 pstring directory;
953 pstring fname;
954 SMB_OFF_T size;
955 int mode;
956 time_t date;
957 int dirtype;
958 int outsize = 0;
959 int numentries = 0;
960 BOOL finished = False;
961 int maxentries;
962 int i;
963 char *p;
964 BOOL ok = False;
965 int status_len;
966 char *path;
967 char status[21];
968 int dptr_num= -1;
969 BOOL check_descend = False;
970 BOOL expect_close = False;
971 BOOL can_open = True;
972 BOOL bad_path = False;
974 *mask = *directory = *fname = 0;
976 /* If we were called as SMBffirst then we must expect close. */
977 if(CVAL(inbuf,smb_com) == SMBffirst)
978 expect_close = True;
980 outsize = set_message(outbuf,1,3,True);
981 maxentries = SVAL(inbuf,smb_vwv0);
982 dirtype = SVAL(inbuf,smb_vwv1);
983 path = smb_buf(inbuf) + 1;
984 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
987 /* dirtype &= ~aDIR; */
989 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
992 if (status_len == 0)
994 pstring dir2;
996 pstrcpy(directory,smb_buf(inbuf)+1);
997 pstrcpy(dir2,smb_buf(inbuf)+1);
998 unix_convert(directory,conn,0,&bad_path,NULL);
999 unix_format(dir2);
1001 if (!check_name(directory,conn))
1002 can_open = False;
1004 p = strrchr(dir2,'/');
1005 if (p == NULL)
1007 pstrcpy(mask,dir2);
1008 *dir2 = 0;
1010 else
1012 *p = 0;
1013 pstrcpy(mask,p+1);
1016 p = strrchr(directory,'/');
1017 if (!p)
1018 *directory = 0;
1019 else
1020 *p = 0;
1022 if (strlen(directory) == 0)
1023 pstrcpy(directory,"./");
1024 bzero(status,21);
1025 CVAL(status,0) = dirtype;
1027 else
1029 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1030 memcpy(mask,status+1,11);
1031 mask[11] = 0;
1032 dirtype = CVAL(status,0) & 0x1F;
1033 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1034 if (!conn->dirptr)
1035 goto SearchEmpty;
1036 string_set(&conn->dirpath,dptr_path(dptr_num));
1037 if (!case_sensitive)
1038 strnorm(mask);
1041 /* turn strings of spaces into a . */
1043 trim_string(mask,NULL," ");
1044 if ((p = strrchr(mask,' ')))
1046 fstring ext;
1047 fstrcpy(ext,p+1);
1048 *p = 0;
1049 trim_string(mask,NULL," ");
1050 pstrcat(mask,".");
1051 pstrcat(mask,ext);
1055 /* Convert the formatted mask. (This code lives in trans2.c) */
1056 mask_convert(mask);
1059 int skip;
1060 p = mask;
1061 while(*p)
1063 if((skip = skip_multibyte_char( *p )) != 0 )
1065 p += skip;
1067 else
1069 if (*p != '?' && *p != '*' && !isdoschar(*p))
1071 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1072 *p = '?';
1074 p++;
1079 if (!strchr(mask,'.') && strlen(mask)>8)
1081 fstring tmp;
1082 fstrcpy(tmp,&mask[8]);
1083 mask[8] = '.';
1084 mask[9] = 0;
1085 pstrcat(mask,tmp);
1088 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1090 if (can_open)
1092 p = smb_buf(outbuf) + 3;
1094 ok = True;
1096 if (status_len == 0)
1098 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1099 if (dptr_num < 0)
1101 if(dptr_num == -2)
1103 if((errno == ENOENT) && bad_path)
1105 unix_ERR_class = ERRDOS;
1106 unix_ERR_code = ERRbadpath;
1108 return (UNIXERROR(ERRDOS,ERRnofids));
1110 return(ERROR(ERRDOS,ERRnofids));
1114 DEBUG(4,("dptr_num is %d\n",dptr_num));
1116 if (ok)
1118 if ((dirtype&0x1F) == aVOLID)
1120 memcpy(p,status,21);
1121 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1122 dptr_fill(p+12,dptr_num);
1123 if (dptr_zero(p+12) && (status_len==0))
1124 numentries = 1;
1125 else
1126 numentries = 0;
1127 p += DIR_STRUCT_SIZE;
1129 else
1131 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1132 conn->dirpath,lp_dontdescend(SNUM(conn))));
1133 if (in_list(conn->dirpath,
1134 lp_dontdescend(SNUM(conn)),True))
1135 check_descend = True;
1137 for (i=numentries;(i<maxentries) && !finished;i++)
1139 finished =
1140 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1141 if (!finished)
1143 memcpy(p,status,21);
1144 make_dir_struct(p,mask,fname,size,mode,date);
1145 dptr_fill(p+12,dptr_num);
1146 numentries++;
1148 p += DIR_STRUCT_SIZE;
1155 SearchEmpty:
1157 if (numentries == 0 || !ok)
1159 CVAL(outbuf,smb_rcls) = ERRDOS;
1160 SSVAL(outbuf,smb_err,ERRnofiles);
1163 /* If we were called as SMBffirst with smb_search_id == NULL
1164 and no entries were found then return error and close dirptr
1165 (X/Open spec) */
1167 if(ok && expect_close && numentries == 0 && status_len == 0)
1169 CVAL(outbuf,smb_rcls) = ERRDOS;
1170 SSVAL(outbuf,smb_err,ERRnofiles);
1171 /* Also close the dptr - we know it's gone */
1172 dptr_close(dptr_num);
1175 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1176 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1177 dptr_close(dptr_num);
1179 SSVAL(outbuf,smb_vwv0,numentries);
1180 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1181 CVAL(smb_buf(outbuf),0) = 5;
1182 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1184 if (Protocol >= PROTOCOL_NT1) {
1185 uint16 flg2 = SVAL(outbuf,smb_flg2);
1186 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1189 outsize += DIR_STRUCT_SIZE*numentries;
1190 smb_setlen(outbuf,outsize - 4);
1192 if ((! *directory) && dptr_path(dptr_num))
1193 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1195 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1196 smb_fn_name(CVAL(inbuf,smb_com)),
1197 mask, directory, dirtype, numentries, maxentries ) );
1199 return(outsize);
1203 /****************************************************************************
1204 reply to a fclose (stop directory search)
1205 ****************************************************************************/
1206 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1208 int outsize = 0;
1209 int status_len;
1210 char *path;
1211 char status[21];
1212 int dptr_num= -1;
1214 outsize = set_message(outbuf,1,0,True);
1215 path = smb_buf(inbuf) + 1;
1216 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1219 if (status_len == 0)
1220 return(ERROR(ERRSRV,ERRsrverror));
1222 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1224 if(dptr_fetch(status+12,&dptr_num)) {
1225 /* Close the dptr - we know it's gone */
1226 dptr_close(dptr_num);
1229 SSVAL(outbuf,smb_vwv0,0);
1231 DEBUG(3,("search close\n"));
1233 return(outsize);
1237 /****************************************************************************
1238 reply to an open
1239 ****************************************************************************/
1240 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1242 pstring fname;
1243 int outsize = 0;
1244 int fmode=0;
1245 int share_mode;
1246 SMB_OFF_T size = 0;
1247 time_t mtime=0;
1248 mode_t unixmode;
1249 int rmode=0;
1250 SMB_STRUCT_STAT sbuf;
1251 BOOL bad_path = False;
1252 files_struct *fsp;
1253 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1255 share_mode = SVAL(inbuf,smb_vwv0);
1257 pstrcpy(fname,smb_buf(inbuf)+1);
1258 unix_convert(fname,conn,0,&bad_path,NULL);
1260 fsp = file_new();
1261 if (!fsp)
1262 return(ERROR(ERRSRV,ERRnofids));
1264 if (!check_name(fname,conn))
1266 if((errno == ENOENT) && bad_path)
1268 unix_ERR_class = ERRDOS;
1269 unix_ERR_code = ERRbadpath;
1271 file_free(fsp);
1272 return(UNIXERROR(ERRDOS,ERRnoaccess));
1275 unixmode = unix_mode(conn,aARCH);
1277 open_file_shared(fsp,conn,fname,share_mode,3,unixmode,
1278 oplock_request,&rmode,NULL);
1280 if (!fsp->open)
1282 if((errno == ENOENT) && bad_path)
1284 unix_ERR_class = ERRDOS;
1285 unix_ERR_code = ERRbadpath;
1287 file_free(fsp);
1288 return(UNIXERROR(ERRDOS,ERRnoaccess));
1291 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1292 close_file(fsp,False);
1293 return(ERROR(ERRDOS,ERRnoaccess));
1296 size = sbuf.st_size;
1297 fmode = dos_mode(conn,fname,&sbuf);
1298 mtime = sbuf.st_mtime;
1300 if (fmode & aDIR) {
1301 DEBUG(3,("attempt to open a directory %s\n",fname));
1302 close_file(fsp,False);
1303 return(ERROR(ERRDOS,ERRnoaccess));
1306 outsize = set_message(outbuf,7,0,True);
1307 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1308 SSVAL(outbuf,smb_vwv1,fmode);
1309 if(lp_dos_filetime_resolution(SNUM(conn)) )
1310 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1311 else
1312 put_dos_date3(outbuf,smb_vwv2,mtime);
1313 SIVAL(outbuf,smb_vwv4,(uint32)size);
1314 SSVAL(outbuf,smb_vwv6,rmode);
1316 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1317 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1320 if(fsp->granted_oplock)
1321 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1322 return(outsize);
1326 /****************************************************************************
1327 reply to an open and X
1328 ****************************************************************************/
1329 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1331 pstring fname;
1332 int smb_mode = SVAL(inbuf,smb_vwv3);
1333 int smb_attr = SVAL(inbuf,smb_vwv5);
1334 /* Breakout the oplock request bits so we can set the
1335 reply bits separately. */
1336 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1337 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1338 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1339 #if 0
1340 int open_flags = SVAL(inbuf,smb_vwv2);
1341 int smb_sattr = SVAL(inbuf,smb_vwv4);
1342 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1343 #endif
1344 int smb_ofun = SVAL(inbuf,smb_vwv8);
1345 mode_t unixmode;
1346 SMB_OFF_T size=0;
1347 int fmode=0,mtime=0,rmode=0;
1348 SMB_STRUCT_STAT sbuf;
1349 int smb_action = 0;
1350 BOOL bad_path = False;
1351 files_struct *fsp;
1353 /* If it's an IPC, pass off the pipe handler. */
1354 if (IS_IPC(conn))
1355 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1357 /* XXXX we need to handle passed times, sattr and flags */
1359 pstrcpy(fname,smb_buf(inbuf));
1360 unix_convert(fname,conn,0,&bad_path,NULL);
1362 fsp = file_new();
1363 if (!fsp)
1364 return(ERROR(ERRSRV,ERRnofids));
1366 if (!check_name(fname,conn))
1368 if((errno == ENOENT) && bad_path)
1370 unix_ERR_class = ERRDOS;
1371 unix_ERR_code = ERRbadpath;
1373 file_free(fsp);
1374 return(UNIXERROR(ERRDOS,ERRnoaccess));
1377 unixmode = unix_mode(conn,smb_attr | aARCH);
1379 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1380 oplock_request, &rmode,&smb_action);
1382 if (!fsp->open)
1384 if((errno == ENOENT) && bad_path)
1386 unix_ERR_class = ERRDOS;
1387 unix_ERR_code = ERRbadpath;
1389 file_free(fsp);
1390 return(UNIXERROR(ERRDOS,ERRnoaccess));
1393 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1394 close_file(fsp,False);
1395 return(ERROR(ERRDOS,ERRnoaccess));
1398 size = sbuf.st_size;
1399 fmode = dos_mode(conn,fname,&sbuf);
1400 mtime = sbuf.st_mtime;
1401 if (fmode & aDIR) {
1402 close_file(fsp,False);
1403 return(ERROR(ERRDOS,ERRnoaccess));
1406 /* If the caller set the extended oplock request bit
1407 and we granted one (by whatever means) - set the
1408 correct bit for extended oplock reply.
1411 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1412 smb_action |= EXTENDED_OPLOCK_GRANTED;
1415 if(ex_oplock_request && fsp->granted_oplock) {
1416 smb_action |= EXTENDED_OPLOCK_GRANTED;
1419 /* If the caller set the core oplock request bit
1420 and we granted one (by whatever means) - set the
1421 correct bit for core oplock reply.
1424 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1425 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1428 if(core_oplock_request && fsp->granted_oplock) {
1429 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1432 set_message(outbuf,15,0,True);
1433 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1434 SSVAL(outbuf,smb_vwv3,fmode);
1435 if(lp_dos_filetime_resolution(SNUM(conn)) )
1436 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1437 else
1438 put_dos_date3(outbuf,smb_vwv4,mtime);
1439 SIVAL(outbuf,smb_vwv6,(uint32)size);
1440 SSVAL(outbuf,smb_vwv8,rmode);
1441 SSVAL(outbuf,smb_vwv11,smb_action);
1443 return chain_reply(inbuf,outbuf,length,bufsize);
1447 /****************************************************************************
1448 reply to a SMBulogoffX
1449 ****************************************************************************/
1450 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1452 uint16 vuid = SVAL(inbuf,smb_uid);
1453 user_struct *vuser = get_valid_user_struct(vuid);
1455 if(vuser == 0) {
1456 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1459 /* in user level security we are supposed to close any files
1460 open by this user */
1461 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1462 file_close_user(vuid);
1465 invalidate_vuid(vuid);
1467 set_message(outbuf,2,0,True);
1469 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1471 return chain_reply(inbuf,outbuf,length,bufsize);
1475 /****************************************************************************
1476 reply to a mknew or a create
1477 ****************************************************************************/
1478 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1480 pstring fname;
1481 int com;
1482 int outsize = 0;
1483 int createmode;
1484 mode_t unixmode;
1485 int ofun = 0;
1486 BOOL bad_path = False;
1487 files_struct *fsp;
1488 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1490 com = SVAL(inbuf,smb_com);
1492 createmode = SVAL(inbuf,smb_vwv0);
1493 pstrcpy(fname,smb_buf(inbuf)+1);
1494 unix_convert(fname,conn,0,&bad_path,NULL);
1496 if (createmode & aVOLID)
1498 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1501 unixmode = unix_mode(conn,createmode);
1503 fsp = file_new();
1504 if (!fsp)
1505 return(ERROR(ERRSRV,ERRnofids));
1507 if (!check_name(fname,conn))
1509 if((errno == ENOENT) && bad_path)
1511 unix_ERR_class = ERRDOS;
1512 unix_ERR_code = ERRbadpath;
1514 file_free(fsp);
1515 return(UNIXERROR(ERRDOS,ERRnoaccess));
1518 if(com == SMBmknew)
1520 /* We should fail if file exists. */
1521 ofun = 0x10;
1523 else
1525 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1526 ofun = 0x12;
1529 /* Open file in dos compatibility share mode. */
1530 open_file_shared(fsp,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1531 oplock_request, NULL, NULL);
1533 if (!fsp->open)
1535 if((errno == ENOENT) && bad_path)
1537 unix_ERR_class = ERRDOS;
1538 unix_ERR_code = ERRbadpath;
1540 file_free(fsp);
1541 return(UNIXERROR(ERRDOS,ERRnoaccess));
1544 outsize = set_message(outbuf,1,0,True);
1545 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1547 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1548 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1551 if(fsp->granted_oplock)
1552 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1554 DEBUG( 2, ( "new file %s\n", fname ) );
1555 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1556 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1558 return(outsize);
1562 /****************************************************************************
1563 reply to a create temporary file
1564 ****************************************************************************/
1565 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1567 pstring fname;
1568 pstring fname2;
1569 int outsize = 0;
1570 int createmode;
1571 mode_t unixmode;
1572 BOOL bad_path = False;
1573 files_struct *fsp;
1574 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1576 createmode = SVAL(inbuf,smb_vwv0);
1577 pstrcpy(fname,smb_buf(inbuf)+1);
1578 pstrcat(fname,"/TMXXXXXX");
1579 unix_convert(fname,conn,0,&bad_path,NULL);
1581 unixmode = unix_mode(conn,createmode);
1583 fsp = file_new();
1584 if (fsp)
1585 return(ERROR(ERRSRV,ERRnofids));
1587 if (!check_name(fname,conn))
1589 if((errno == ENOENT) && bad_path)
1591 unix_ERR_class = ERRDOS;
1592 unix_ERR_code = ERRbadpath;
1594 file_free(fsp);
1595 return(UNIXERROR(ERRDOS,ERRnoaccess));
1598 pstrcpy(fname2,(char *)mktemp(fname));
1600 /* Open file in dos compatibility share mode. */
1601 /* We should fail if file exists. */
1602 open_file_shared(fsp,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1603 oplock_request, NULL, NULL);
1605 if (!fsp->open)
1607 if((errno == ENOENT) && bad_path)
1609 unix_ERR_class = ERRDOS;
1610 unix_ERR_code = ERRbadpath;
1612 file_free(fsp);
1613 return(UNIXERROR(ERRDOS,ERRnoaccess));
1616 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1617 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1618 CVAL(smb_buf(outbuf),0) = 4;
1619 pstrcpy(smb_buf(outbuf) + 1,fname2);
1621 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1622 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1625 if(fsp->granted_oplock)
1626 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1628 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1629 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1630 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1632 return(outsize);
1636 /*******************************************************************
1637 check if a user is allowed to delete a file
1638 ********************************************************************/
1639 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1641 SMB_STRUCT_STAT sbuf;
1642 int fmode;
1644 if (!CAN_WRITE(conn)) return(False);
1646 if (dos_lstat(fname,&sbuf) != 0) return(False);
1647 fmode = dos_mode(conn,fname,&sbuf);
1648 if (fmode & aDIR) return(False);
1649 if (!lp_delete_readonly(SNUM(conn))) {
1650 if (fmode & aRONLY) return(False);
1652 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1653 return(False);
1654 if (!check_file_sharing(conn,fname,False)) return(False);
1655 return(True);
1658 /****************************************************************************
1659 reply to a unlink
1660 ****************************************************************************/
1661 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1663 int outsize = 0;
1664 pstring name;
1665 int dirtype;
1666 pstring directory;
1667 pstring mask;
1668 char *p;
1669 int count=0;
1670 int error = ERRnoaccess;
1671 BOOL has_wild;
1672 BOOL exists=False;
1673 BOOL bad_path = False;
1675 *directory = *mask = 0;
1677 dirtype = SVAL(inbuf,smb_vwv0);
1679 pstrcpy(name,smb_buf(inbuf) + 1);
1681 DEBUG(3,("reply_unlink : %s\n",name));
1683 unix_convert(name,conn,0,&bad_path,NULL);
1685 p = strrchr(name,'/');
1686 if (!p) {
1687 pstrcpy(directory,"./");
1688 pstrcpy(mask,name);
1689 } else {
1690 *p = 0;
1691 pstrcpy(directory,name);
1692 pstrcpy(mask,p+1);
1695 if (is_mangled(mask))
1696 check_mangled_cache( mask );
1698 has_wild = strchr(mask,'*') || strchr(mask,'?');
1700 if (!has_wild) {
1701 pstrcat(directory,"/");
1702 pstrcat(directory,mask);
1703 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++;
1704 if (!count) exists = file_exist(directory,NULL);
1705 } else {
1706 void *dirptr = NULL;
1707 char *dname;
1709 if (check_name(directory,conn))
1710 dirptr = OpenDir(conn, directory, True);
1712 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1713 the pattern matches against the long name, otherwise the short name
1714 We don't implement this yet XXXX
1717 if (dirptr)
1719 error = ERRbadfile;
1721 if (strequal(mask,"????????.???"))
1722 pstrcpy(mask,"*");
1724 while ((dname = ReadDirName(dirptr)))
1726 pstring fname;
1727 pstrcpy(fname,dname);
1729 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1731 error = ERRnoaccess;
1732 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1733 if (!can_delete(fname,conn,dirtype)) continue;
1734 if (!dos_unlink(fname)) count++;
1735 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1737 CloseDir(dirptr);
1741 if (count == 0) {
1742 if (exists)
1743 return(ERROR(ERRDOS,error));
1744 else
1746 if((errno == ENOENT) && bad_path)
1748 unix_ERR_class = ERRDOS;
1749 unix_ERR_code = ERRbadpath;
1751 return(UNIXERROR(ERRDOS,error));
1755 outsize = set_message(outbuf,0,0,True);
1757 return(outsize);
1761 /****************************************************************************
1762 reply to a readbraw (core+ protocol)
1763 ****************************************************************************/
1764 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1766 size_t maxcount,mincount;
1767 size_t nread = 0;
1768 SMB_OFF_T startpos;
1769 char *header = outbuf;
1770 ssize_t ret=0;
1771 files_struct *fsp;
1774 * Special check if an oplock break has been issued
1775 * and the readraw request croses on the wire, we must
1776 * return a zero length response here.
1779 if(global_oplock_break)
1781 _smb_setlen(header,0);
1782 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1783 DEBUG(5,("readbraw - oplock break finished\n"));
1784 return -1;
1787 fsp = file_fsp(inbuf,smb_vwv0);
1789 startpos = IVAL(inbuf,smb_vwv1);
1790 #ifdef LARGE_SMB_OFF_T
1791 if(CVAL(inbuf,smb_wct) == 10) {
1793 * This is a large offset (64 bit) read.
1795 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1796 if(startpos < 0) {
1797 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1798 (double)startpos ));
1799 _smb_setlen(header,0);
1800 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1801 return(-1);
1804 #endif /* LARGE_SMB_OFF_T */
1805 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1806 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1808 /* ensure we don't overrun the packet size */
1809 maxcount = MIN(65535,maxcount);
1810 maxcount = MAX(mincount,maxcount);
1812 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1813 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1814 _smb_setlen(header,0);
1815 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1816 return(-1);
1819 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1821 SMB_OFF_T size = fsp->size;
1822 SMB_OFF_T sizeneeded = startpos + maxcount;
1824 if (size < sizeneeded)
1826 SMB_STRUCT_STAT st;
1827 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1828 size = st.st_size;
1829 if (!fsp->can_write)
1830 fsp->size = size;
1833 nread = MIN(maxcount,(size - startpos));
1836 if (nread < mincount)
1837 nread = 0;
1839 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1840 fsp->fnum, (double)startpos,
1841 maxcount, mincount, nread ) );
1843 #if UNSAFE_READRAW
1845 int predict=0;
1846 _smb_setlen(header,nread);
1848 #if USE_READ_PREDICTION
1849 if (!fsp->can_write)
1850 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1851 #endif /* USE_READ_PREDICTION */
1853 if ((nread-predict) > 0)
1854 seek_file(fsp,startpos + predict);
1856 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict,
1857 startpos+predict);
1860 if (ret != nread+4)
1861 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1862 fsp->fsp_name,startpos,nread,ret));
1864 #else /* UNSAFE_READRAW */
1865 ret = read_file(fsp,header+4,startpos,nread);
1866 if (ret < mincount) ret = 0;
1868 _smb_setlen(header,ret);
1869 transfer_file(0,Client,0,header,4+ret,0);
1870 #endif /* UNSAFE_READRAW */
1872 DEBUG(5,("readbraw finished\n"));
1873 return -1;
1877 /****************************************************************************
1878 reply to a lockread (core+ protocol)
1879 ****************************************************************************/
1880 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1882 ssize_t nread = -1;
1883 char *data;
1884 int outsize = 0;
1885 SMB_OFF_T startpos;
1886 size_t numtoread;
1887 int eclass;
1888 uint32 ecode;
1889 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1891 CHECK_FSP(fsp,conn);
1892 CHECK_READ(fsp);
1893 CHECK_ERROR(fsp);
1895 numtoread = SVAL(inbuf,smb_vwv1);
1896 startpos = IVAL(inbuf,smb_vwv2);
1898 outsize = set_message(outbuf,5,3,True);
1899 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1900 data = smb_buf(outbuf) + 3;
1902 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1903 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1905 * A blocking lock was requested. Package up
1906 * this smb into a queued request and push it
1907 * onto the blocking lock queue.
1909 if(push_blocking_lock_request(inbuf, length, -1, 0))
1910 return -1;
1912 return (ERROR(eclass,ecode));
1915 nread = read_file(fsp,data,startpos,numtoread);
1917 if (nread < 0)
1918 return(UNIXERROR(ERRDOS,ERRnoaccess));
1920 outsize += nread;
1921 SSVAL(outbuf,smb_vwv0,nread);
1922 SSVAL(outbuf,smb_vwv5,nread+3);
1923 SSVAL(smb_buf(outbuf),1,nread);
1925 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1926 fsp->fnum, numtoread, nread ) );
1928 return(outsize);
1932 /****************************************************************************
1933 reply to a read
1934 ****************************************************************************/
1935 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1937 size_t numtoread;
1938 ssize_t nread = 0;
1939 char *data;
1940 SMB_OFF_T startpos;
1941 int outsize = 0;
1942 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1944 CHECK_FSP(fsp,conn);
1945 CHECK_READ(fsp);
1946 CHECK_ERROR(fsp);
1948 numtoread = SVAL(inbuf,smb_vwv1);
1949 startpos = IVAL(inbuf,smb_vwv2);
1951 outsize = set_message(outbuf,5,3,True);
1952 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1953 data = smb_buf(outbuf) + 3;
1955 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
1956 return(ERROR(ERRDOS,ERRlock));
1958 if (numtoread > 0)
1959 nread = read_file(fsp,data,startpos,numtoread);
1961 if (nread < 0)
1962 return(UNIXERROR(ERRDOS,ERRnoaccess));
1964 outsize += nread;
1965 SSVAL(outbuf,smb_vwv0,nread);
1966 SSVAL(outbuf,smb_vwv5,nread+3);
1967 CVAL(smb_buf(outbuf),0) = 1;
1968 SSVAL(smb_buf(outbuf),1,nread);
1970 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1971 fsp->fnum, numtoread, nread ) );
1973 return(outsize);
1977 /****************************************************************************
1978 reply to a read and X
1979 ****************************************************************************/
1980 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1982 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1983 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1984 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1985 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1986 ssize_t nread = -1;
1987 char *data;
1989 /* If it's an IPC, pass off the pipe handler. */
1990 if (IS_IPC(conn))
1991 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1993 CHECK_FSP(fsp,conn);
1994 CHECK_READ(fsp);
1995 CHECK_ERROR(fsp);
1997 set_message(outbuf,12,0,True);
1998 data = smb_buf(outbuf);
2000 #ifdef LARGE_SMB_OFF_T
2001 if(CVAL(inbuf,smb_wct) == 12) {
2003 * This is a large offset (64 bit) read.
2005 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2007 #endif /* LARGE_SMB_OFF_T */
2009 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2010 return(ERROR(ERRDOS,ERRlock));
2011 nread = read_file(fsp,data,startpos,smb_maxcnt);
2013 if (nread < 0)
2014 return(UNIXERROR(ERRDOS,ERRnoaccess));
2016 SSVAL(outbuf,smb_vwv5,nread);
2017 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2018 SSVAL(smb_buf(outbuf),-2,nread);
2020 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2021 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2023 return chain_reply(inbuf,outbuf,length,bufsize);
2026 /****************************************************************************
2027 reply to a writebraw (core+ or LANMAN1.0 protocol)
2028 ****************************************************************************/
2029 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2031 ssize_t nwritten=0;
2032 ssize_t total_written=0;
2033 size_t numtowrite=0;
2034 size_t tcount;
2035 SMB_OFF_T startpos;
2036 char *data=NULL;
2037 BOOL write_through;
2038 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2039 int outsize = 0;
2041 CHECK_FSP(fsp,conn);
2042 CHECK_WRITE(fsp);
2043 CHECK_ERROR(fsp);
2045 tcount = IVAL(inbuf,smb_vwv1);
2046 startpos = IVAL(inbuf,smb_vwv3);
2047 write_through = BITSETW(inbuf+smb_vwv7,0);
2049 /* We have to deal with slightly different formats depending
2050 on whether we are using the core+ or lanman1.0 protocol */
2051 if(Protocol <= PROTOCOL_COREPLUS) {
2052 numtowrite = SVAL(smb_buf(inbuf),-2);
2053 data = smb_buf(inbuf);
2054 } else {
2055 numtowrite = SVAL(inbuf,smb_vwv10);
2056 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2059 /* force the error type */
2060 CVAL(inbuf,smb_com) = SMBwritec;
2061 CVAL(outbuf,smb_com) = SMBwritec;
2063 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2064 return(ERROR(ERRDOS,ERRlock));
2066 if (seek_file(fsp,startpos) != startpos)
2067 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2069 if (numtowrite>0)
2070 nwritten = write_file(fsp,data,numtowrite);
2072 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2073 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2075 if (nwritten < numtowrite)
2076 return(UNIXERROR(ERRHRD,ERRdiskfull));
2078 total_written = nwritten;
2080 /* Return a message to the redirector to tell it
2081 to send more bytes */
2082 CVAL(outbuf,smb_com) = SMBwritebraw;
2083 SSVALS(outbuf,smb_vwv0,-1);
2084 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2085 send_smb(Client,outbuf);
2087 /* Now read the raw data into the buffer and write it */
2088 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2089 exit_server("secondary writebraw failed");
2092 /* Even though this is not an smb message, smb_len
2093 returns the generic length of an smb message */
2094 numtowrite = smb_len(inbuf);
2096 if (tcount > nwritten+numtowrite) {
2097 DEBUG(3,("Client overestimated the write %d %d %d\n",
2098 tcount,nwritten,numtowrite));
2101 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2102 startpos+nwritten);
2103 total_written += nwritten;
2105 /* Set up outbuf to return the correct return */
2106 outsize = set_message(outbuf,1,0,True);
2107 CVAL(outbuf,smb_com) = SMBwritec;
2108 SSVAL(outbuf,smb_vwv0,total_written);
2110 if (nwritten < (ssize_t)numtowrite) {
2111 CVAL(outbuf,smb_rcls) = ERRHRD;
2112 SSVAL(outbuf,smb_err,ERRdiskfull);
2115 if (lp_syncalways(SNUM(conn)) || write_through)
2116 sync_file(conn,fsp);
2118 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2119 fsp->fnum, (double)startpos, numtowrite, total_written));
2121 /* we won't return a status if write through is not selected - this
2122 follows what WfWg does */
2123 if (!write_through && total_written==tcount)
2124 return(-1);
2126 return(outsize);
2129 /****************************************************************************
2130 reply to a writeunlock (core+)
2131 ****************************************************************************/
2132 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2134 ssize_t nwritten = -1;
2135 size_t numtowrite;
2136 SMB_OFF_T startpos;
2137 char *data;
2138 int eclass;
2139 uint32 ecode;
2140 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2141 int outsize = 0;
2143 CHECK_FSP(fsp,conn);
2144 CHECK_WRITE(fsp);
2145 CHECK_ERROR(fsp);
2147 numtowrite = SVAL(inbuf,smb_vwv1);
2148 startpos = IVAL(inbuf,smb_vwv2);
2149 data = smb_buf(inbuf) + 3;
2151 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2152 return(ERROR(ERRDOS,ERRlock));
2154 seek_file(fsp,startpos);
2156 /* The special X/Open SMB protocol handling of
2157 zero length writes is *NOT* done for
2158 this call */
2159 if(numtowrite == 0)
2160 nwritten = 0;
2161 else
2162 nwritten = write_file(fsp,data,numtowrite);
2164 if (lp_syncalways(SNUM(conn)))
2165 sync_file(conn,fsp);
2167 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2168 return(UNIXERROR(ERRDOS,ERRnoaccess));
2170 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2171 return(ERROR(eclass,ecode));
2173 outsize = set_message(outbuf,1,0,True);
2175 SSVAL(outbuf,smb_vwv0,nwritten);
2177 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2178 fsp->fnum, numtowrite, nwritten ) );
2180 return(outsize);
2183 /****************************************************************************
2184 reply to a write
2185 ****************************************************************************/
2186 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2188 size_t numtowrite;
2189 ssize_t nwritten = -1;
2190 SMB_OFF_T startpos;
2191 char *data;
2192 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2193 int outsize = 0;
2195 CHECK_FSP(fsp,conn);
2196 CHECK_WRITE(fsp);
2197 CHECK_ERROR(fsp);
2199 numtowrite = SVAL(inbuf,smb_vwv1);
2200 startpos = IVAL(inbuf,smb_vwv2);
2201 data = smb_buf(inbuf) + 3;
2203 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2204 return(ERROR(ERRDOS,ERRlock));
2206 seek_file(fsp,startpos);
2208 /* X/Open SMB protocol says that if smb_vwv1 is
2209 zero then the file size should be extended or
2210 truncated to the size given in smb_vwv[2-3] */
2211 if(numtowrite == 0)
2212 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2213 else
2214 nwritten = write_file(fsp,data,numtowrite);
2216 if (lp_syncalways(SNUM(conn)))
2217 sync_file(conn,fsp);
2219 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2220 return(UNIXERROR(ERRDOS,ERRnoaccess));
2222 outsize = set_message(outbuf,1,0,True);
2224 SSVAL(outbuf,smb_vwv0,nwritten);
2226 if (nwritten < (ssize_t)numtowrite) {
2227 CVAL(outbuf,smb_rcls) = ERRHRD;
2228 SSVAL(outbuf,smb_err,ERRdiskfull);
2231 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2232 fsp->fnum, numtowrite, nwritten));
2234 return(outsize);
2238 /****************************************************************************
2239 reply to a write and X
2240 ****************************************************************************/
2241 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2243 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2244 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2245 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2246 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2247 ssize_t nwritten = -1;
2248 int smb_doff = SVAL(inbuf,smb_vwv11);
2249 char *data;
2251 CHECK_FSP(fsp,conn);
2252 CHECK_WRITE(fsp);
2253 CHECK_ERROR(fsp);
2255 data = smb_base(inbuf) + smb_doff;
2257 #ifdef LARGE_SMB_OFF_T
2258 if(CVAL(inbuf,smb_wct) == 14) {
2260 * This is a large offset (64 bit) write.
2262 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2264 #endif /* LARGE_SMB_OFF_T */
2266 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2267 return(ERROR(ERRDOS,ERRlock));
2269 seek_file(fsp,startpos);
2271 /* X/Open SMB protocol says that, unlike SMBwrite
2272 if the length is zero then NO truncation is
2273 done, just a write of zero. To truncate a file,
2274 use SMBwrite. */
2275 if(numtowrite == 0)
2276 nwritten = 0;
2277 else
2278 nwritten = write_file(fsp,data,numtowrite);
2280 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2281 return(UNIXERROR(ERRDOS,ERRnoaccess));
2283 set_message(outbuf,6,0,True);
2285 SSVAL(outbuf,smb_vwv2,nwritten);
2287 if (nwritten < (ssize_t)numtowrite) {
2288 CVAL(outbuf,smb_rcls) = ERRHRD;
2289 SSVAL(outbuf,smb_err,ERRdiskfull);
2292 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2293 fsp->fnum, numtowrite, nwritten));
2295 if (lp_syncalways(SNUM(conn)) || write_through)
2296 sync_file(conn,fsp);
2298 return chain_reply(inbuf,outbuf,length,bufsize);
2302 /****************************************************************************
2303 reply to a lseek
2304 ****************************************************************************/
2305 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2307 SMB_OFF_T startpos;
2308 SMB_OFF_T res= -1;
2309 int mode,umode;
2310 int outsize = 0;
2311 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2313 CHECK_FSP(fsp,conn);
2314 CHECK_ERROR(fsp);
2316 mode = SVAL(inbuf,smb_vwv1) & 3;
2317 startpos = IVAL(inbuf,smb_vwv2);
2319 switch (mode & 3)
2321 case 0: umode = SEEK_SET; break;
2322 case 1: umode = SEEK_CUR; break;
2323 case 2: umode = SEEK_END; break;
2324 default:
2325 umode = SEEK_SET; break;
2328 res = sys_lseek(fsp->fd_ptr->fd,startpos,umode);
2329 fsp->pos = res;
2331 outsize = set_message(outbuf,2,0,True);
2332 SIVALS(outbuf,smb_vwv0,res);
2334 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2335 fsp->fnum, (double)startpos, mode));
2337 return(outsize);
2340 /****************************************************************************
2341 reply to a flush
2342 ****************************************************************************/
2343 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2345 int outsize = set_message(outbuf,0,0,True);
2346 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2348 if (fsp) {
2349 CHECK_FSP(fsp,conn);
2350 CHECK_ERROR(fsp);
2353 if (!fsp) {
2354 file_sync_all(conn);
2355 } else {
2356 sync_file(conn,fsp);
2359 DEBUG(3,("flush\n"));
2360 return(outsize);
2364 /****************************************************************************
2365 reply to a exit
2366 ****************************************************************************/
2367 int reply_exit(connection_struct *conn,
2368 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2370 int outsize = set_message(outbuf,0,0,True);
2371 DEBUG(3,("exit\n"));
2373 return(outsize);
2377 /****************************************************************************
2378 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2379 ****************************************************************************/
2380 int reply_close(connection_struct *conn,
2381 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2383 int outsize = 0;
2384 time_t mtime;
2385 int32 eclass = 0, err = 0;
2386 files_struct *fsp = NULL;
2388 outsize = set_message(outbuf,0,0,True);
2390 /* If it's an IPC, pass off to the pipe handler. */
2391 if (IS_IPC(conn)) {
2392 return reply_pipe_close(conn, inbuf,outbuf);
2395 fsp = file_fsp(inbuf,smb_vwv0);
2398 * We can only use CHECK_FSP if we know it's not a directory.
2401 if(!fsp || !fsp->open || (fsp->conn != conn))
2402 return(ERROR(ERRDOS,ERRbadfid));
2404 if(HAS_CACHED_ERROR(fsp)) {
2405 eclass = fsp->wbmpx_ptr->wr_errclass;
2406 err = fsp->wbmpx_ptr->wr_error;
2409 if(fsp->is_directory) {
2411 * Special case - close NT SMB directory
2412 * handle.
2414 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2415 close_directory(fsp);
2416 } else {
2418 * Close ordinary file.
2420 mtime = make_unix_date3(inbuf+smb_vwv1);
2422 /* try and set the date */
2423 set_filetime(conn, fsp->fsp_name,mtime);
2425 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2426 fsp->fd_ptr->fd, fsp->fnum,
2427 conn->num_files_open));
2429 close_file(fsp,True);
2432 /* We have a cached error */
2433 if(eclass || err)
2434 return(ERROR(eclass,err));
2436 return(outsize);
2440 /****************************************************************************
2441 reply to a writeclose (Core+ protocol)
2442 ****************************************************************************/
2443 int reply_writeclose(connection_struct *conn,
2444 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2446 size_t numtowrite;
2447 ssize_t nwritten = -1;
2448 int outsize = 0;
2449 SMB_OFF_T startpos;
2450 char *data;
2451 time_t mtime;
2452 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2454 CHECK_FSP(fsp,conn);
2455 CHECK_WRITE(fsp);
2456 CHECK_ERROR(fsp);
2458 numtowrite = SVAL(inbuf,smb_vwv1);
2459 startpos = IVAL(inbuf,smb_vwv2);
2460 mtime = make_unix_date3(inbuf+smb_vwv4);
2461 data = smb_buf(inbuf) + 1;
2463 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2464 return(ERROR(ERRDOS,ERRlock));
2466 seek_file(fsp,startpos);
2468 nwritten = write_file(fsp,data,numtowrite);
2470 set_filetime(conn, fsp->fsp_name,mtime);
2472 close_file(fsp,True);
2474 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2475 fsp->fnum, numtowrite, nwritten,
2476 conn->num_files_open));
2478 if (nwritten <= 0)
2479 return(UNIXERROR(ERRDOS,ERRnoaccess));
2481 outsize = set_message(outbuf,1,0,True);
2483 SSVAL(outbuf,smb_vwv0,nwritten);
2484 return(outsize);
2488 /****************************************************************************
2489 reply to a lock
2490 ****************************************************************************/
2491 int reply_lock(connection_struct *conn,
2492 char *inbuf,char *outbuf, int length, int dum_buffsize)
2494 int outsize = set_message(outbuf,0,0,True);
2495 SMB_OFF_T count,offset;
2496 int eclass;
2497 uint32 ecode;
2498 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2500 CHECK_FSP(fsp,conn);
2501 CHECK_ERROR(fsp);
2503 count = IVAL(inbuf,smb_vwv1);
2504 offset = IVAL(inbuf,smb_vwv3);
2506 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2507 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2509 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2510 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2512 * A blocking lock was requested. Package up
2513 * this smb into a queued request and push it
2514 * onto the blocking lock queue.
2516 if(push_blocking_lock_request(inbuf, length, -1, 0))
2517 return -1;
2519 return (ERROR(eclass,ecode));
2522 return(outsize);
2526 /****************************************************************************
2527 reply to a unlock
2528 ****************************************************************************/
2529 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2531 int outsize = set_message(outbuf,0,0,True);
2532 SMB_OFF_T count,offset;
2533 int eclass;
2534 uint32 ecode;
2535 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2537 CHECK_FSP(fsp,conn);
2538 CHECK_ERROR(fsp);
2540 count = IVAL(inbuf,smb_vwv1);
2541 offset = IVAL(inbuf,smb_vwv3);
2543 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2544 return (ERROR(eclass,ecode));
2546 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2547 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2549 return(outsize);
2553 /****************************************************************************
2554 reply to a tdis
2555 ****************************************************************************/
2556 int reply_tdis(connection_struct *conn,
2557 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2559 int outsize = set_message(outbuf,0,0,True);
2560 uint16 vuid;
2562 vuid = SVAL(inbuf,smb_uid);
2564 if (!conn) {
2565 DEBUG(4,("Invalid connection in tdis\n"));
2566 return(ERROR(ERRSRV,ERRinvnid));
2569 conn->used = False;
2571 close_cnum(conn,vuid);
2573 return outsize;
2578 /****************************************************************************
2579 reply to a echo
2580 ****************************************************************************/
2581 int reply_echo(connection_struct *conn,
2582 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2584 int smb_reverb = SVAL(inbuf,smb_vwv0);
2585 int seq_num;
2586 int data_len = smb_buflen(inbuf);
2587 int outsize = set_message(outbuf,1,data_len,True);
2589 /* copy any incoming data back out */
2590 if (data_len > 0)
2591 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2593 if (smb_reverb > 100) {
2594 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2595 smb_reverb = 100;
2598 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2599 SSVAL(outbuf,smb_vwv0,seq_num);
2601 smb_setlen(outbuf,outsize - 4);
2603 send_smb(Client,outbuf);
2606 DEBUG(3,("echo %d times\n", smb_reverb));
2608 return -1;
2612 /****************************************************************************
2613 reply to a printopen
2614 ****************************************************************************/
2615 int reply_printopen(connection_struct *conn,
2616 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2618 pstring fname;
2619 pstring fname2;
2620 int outsize = 0;
2621 files_struct *fsp;
2623 *fname = *fname2 = 0;
2625 if (!CAN_PRINT(conn))
2626 return(ERROR(ERRDOS,ERRnoaccess));
2629 pstring s;
2630 char *p;
2631 pstrcpy(s,smb_buf(inbuf)+1);
2632 p = s;
2633 while (*p) {
2634 if (!(isalnum((int)*p) || strchr("._-",*p)))
2635 *p = 'X';
2636 p++;
2639 if (strlen(s) > 10) s[10] = 0;
2641 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2644 fsp = file_new();
2645 if (!fsp)
2646 return(ERROR(ERRSRV,ERRnofids));
2648 pstrcpy(fname2,(char *)mktemp(fname));
2650 if (!check_name(fname2,conn)) {
2651 file_free(fsp);
2652 return(ERROR(ERRDOS,ERRnoaccess));
2655 /* Open for exclusive use, write only. */
2656 open_file_shared(fsp,conn,fname2,
2657 (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0),
2658 0, NULL, NULL);
2660 if (!fsp->open) {
2661 file_free(fsp);
2662 return(UNIXERROR(ERRDOS,ERRnoaccess));
2665 /* force it to be a print file */
2666 fsp->print_file = True;
2668 outsize = set_message(outbuf,1,0,True);
2669 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2671 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2672 fname2, fsp->fd_ptr->fd, fsp->fnum));
2674 return(outsize);
2678 /****************************************************************************
2679 reply to a printclose
2680 ****************************************************************************/
2681 int reply_printclose(connection_struct *conn,
2682 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2684 int outsize = set_message(outbuf,0,0,True);
2685 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2687 CHECK_FSP(fsp,conn);
2688 CHECK_ERROR(fsp);
2690 if (!CAN_PRINT(conn))
2691 return(ERROR(ERRDOS,ERRnoaccess));
2693 DEBUG(3,("printclose fd=%d fnum=%d\n",
2694 fsp->fd_ptr->fd,fsp->fnum));
2696 close_file(fsp,True);
2698 return(outsize);
2702 /****************************************************************************
2703 reply to a printqueue
2704 ****************************************************************************/
2705 int reply_printqueue(connection_struct *conn,
2706 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2708 int outsize = set_message(outbuf,2,3,True);
2709 int max_count = SVAL(inbuf,smb_vwv0);
2710 int start_index = SVAL(inbuf,smb_vwv1);
2712 /* we used to allow the client to get the cnum wrong, but that
2713 is really quite gross and only worked when there was only
2714 one printer - I think we should now only accept it if they
2715 get it right (tridge) */
2716 if (!CAN_PRINT(conn))
2717 return(ERROR(ERRDOS,ERRnoaccess));
2719 SSVAL(outbuf,smb_vwv0,0);
2720 SSVAL(outbuf,smb_vwv1,0);
2721 CVAL(smb_buf(outbuf),0) = 1;
2722 SSVAL(smb_buf(outbuf),1,0);
2724 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2725 start_index, max_count));
2728 print_queue_struct *queue = NULL;
2729 char *p = smb_buf(outbuf) + 3;
2730 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2731 int num_to_get = ABS(max_count);
2732 int first = (max_count>0?start_index:start_index+max_count+1);
2733 int i;
2735 if (first >= count)
2736 num_to_get = 0;
2737 else
2738 num_to_get = MIN(num_to_get,count-first);
2741 for (i=first;i<first+num_to_get;i++) {
2742 put_dos_date2(p,0,queue[i].time);
2743 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2744 SSVAL(p,5,printjob_encode(SNUM(conn),
2745 queue[i].job));
2746 SIVAL(p,7,queue[i].size);
2747 CVAL(p,11) = 0;
2748 StrnCpy(p+12,queue[i].user,16);
2749 p += 28;
2752 if (count > 0) {
2753 outsize = set_message(outbuf,2,28*count+3,False);
2754 SSVAL(outbuf,smb_vwv0,count);
2755 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2756 CVAL(smb_buf(outbuf),0) = 1;
2757 SSVAL(smb_buf(outbuf),1,28*count);
2760 if (queue) free(queue);
2762 DEBUG(3,("%d entries returned in queue\n",count));
2765 return(outsize);
2769 /****************************************************************************
2770 reply to a printwrite
2771 ****************************************************************************/
2772 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2774 int numtowrite;
2775 int outsize = set_message(outbuf,0,0,True);
2776 char *data;
2777 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2779 if (!CAN_PRINT(conn))
2780 return(ERROR(ERRDOS,ERRnoaccess));
2782 CHECK_FSP(fsp,conn);
2783 CHECK_WRITE(fsp);
2784 CHECK_ERROR(fsp);
2786 numtowrite = SVAL(smb_buf(inbuf),1);
2787 data = smb_buf(inbuf) + 3;
2789 if (write_file(fsp,data,numtowrite) != numtowrite)
2790 return(UNIXERROR(ERRDOS,ERRnoaccess));
2792 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2794 return(outsize);
2798 /****************************************************************************
2799 reply to a mkdir
2800 ****************************************************************************/
2801 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2803 pstring directory;
2804 int outsize,ret= -1;
2805 BOOL bad_path = False;
2807 pstrcpy(directory,smb_buf(inbuf) + 1);
2808 unix_convert(directory,conn,0,&bad_path,NULL);
2810 if (check_name(directory, conn))
2811 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2813 if (ret < 0)
2815 if((errno == ENOENT) && bad_path)
2817 unix_ERR_class = ERRDOS;
2818 unix_ERR_code = ERRbadpath;
2820 return(UNIXERROR(ERRDOS,ERRnoaccess));
2823 outsize = set_message(outbuf,0,0,True);
2825 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2827 return(outsize);
2830 /****************************************************************************
2831 Static function used by reply_rmdir to delete an entire directory
2832 tree recursively.
2833 ****************************************************************************/
2834 static BOOL recursive_rmdir(char *directory)
2836 char *dname = NULL;
2837 BOOL ret = False;
2838 void *dirptr = OpenDir(NULL, directory, False);
2840 if(dirptr == NULL)
2841 return True;
2843 while((dname = ReadDirName(dirptr)))
2845 pstring fullname;
2846 SMB_STRUCT_STAT st;
2848 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2849 continue;
2851 /* Construct the full name. */
2852 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2854 errno = ENOMEM;
2855 ret = True;
2856 break;
2858 pstrcpy(fullname, directory);
2859 pstrcat(fullname, "/");
2860 pstrcat(fullname, dname);
2862 if(dos_lstat(fullname, &st) != 0)
2864 ret = True;
2865 break;
2868 if(st.st_mode & S_IFDIR)
2870 if(recursive_rmdir(fullname)!=0)
2872 ret = True;
2873 break;
2875 if(dos_rmdir(fullname) != 0)
2877 ret = True;
2878 break;
2881 else if(dos_unlink(fullname) != 0)
2883 ret = True;
2884 break;
2887 CloseDir(dirptr);
2888 return ret;
2891 /****************************************************************************
2892 reply to a rmdir
2893 ****************************************************************************/
2894 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2896 pstring directory;
2897 int outsize = 0;
2898 BOOL ok = False;
2899 BOOL bad_path = False;
2901 pstrcpy(directory,smb_buf(inbuf) + 1);
2902 unix_convert(directory,conn, NULL,&bad_path,NULL);
2904 if (check_name(directory,conn))
2907 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2908 ok = (dos_rmdir(directory) == 0);
2909 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2911 /* Check to see if the only thing in this directory are
2912 vetoed files/directories. If so then delete them and
2913 retry. If we fail to delete any of them (and we *don't*
2914 do a recursive delete) then fail the rmdir. */
2915 BOOL all_veto_files = True;
2916 char *dname;
2917 void *dirptr = OpenDir(conn, directory, False);
2919 if(dirptr != NULL)
2921 int dirpos = TellDir(dirptr);
2922 while ((dname = ReadDirName(dirptr)))
2924 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2925 continue;
2926 if(!IS_VETO_PATH(conn, dname))
2928 all_veto_files = False;
2929 break;
2932 if(all_veto_files)
2934 SeekDir(dirptr,dirpos);
2935 while ((dname = ReadDirName(dirptr)))
2937 pstring fullname;
2938 SMB_STRUCT_STAT st;
2940 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2941 continue;
2943 /* Construct the full name. */
2944 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2946 errno = ENOMEM;
2947 break;
2949 pstrcpy(fullname, directory);
2950 pstrcat(fullname, "/");
2951 pstrcat(fullname, dname);
2953 if(dos_lstat(fullname, &st) != 0)
2954 break;
2955 if(st.st_mode & S_IFDIR)
2957 if(lp_recursive_veto_delete(SNUM(conn)))
2959 if(recursive_rmdir(fullname) != 0)
2960 break;
2962 if(dos_rmdir(fullname) != 0)
2963 break;
2965 else if(dos_unlink(fullname) != 0)
2966 break;
2968 CloseDir(dirptr);
2969 /* Retry the rmdir */
2970 ok = (dos_rmdir(directory) == 0);
2972 else
2973 CloseDir(dirptr);
2975 else
2976 errno = ENOTEMPTY;
2979 if (!ok)
2980 DEBUG(3,("couldn't remove directory %s : %s\n",
2981 directory,strerror(errno)));
2984 if (!ok)
2986 if((errno == ENOENT) && bad_path)
2988 unix_ERR_class = ERRDOS;
2989 unix_ERR_code = ERRbadpath;
2991 return(UNIXERROR(ERRDOS,ERRbadpath));
2994 outsize = set_message(outbuf,0,0,True);
2996 DEBUG( 3, ( "rmdir %s\n", directory ) );
2998 return(outsize);
3002 /*******************************************************************
3003 resolve wildcards in a filename rename
3004 ********************************************************************/
3005 static BOOL resolve_wildcards(char *name1,char *name2)
3007 fstring root1,root2;
3008 fstring ext1,ext2;
3009 char *p,*p2;
3011 name1 = strrchr(name1,'/');
3012 name2 = strrchr(name2,'/');
3014 if (!name1 || !name2) return(False);
3016 fstrcpy(root1,name1);
3017 fstrcpy(root2,name2);
3018 p = strrchr(root1,'.');
3019 if (p) {
3020 *p = 0;
3021 fstrcpy(ext1,p+1);
3022 } else {
3023 fstrcpy(ext1,"");
3025 p = strrchr(root2,'.');
3026 if (p) {
3027 *p = 0;
3028 fstrcpy(ext2,p+1);
3029 } else {
3030 fstrcpy(ext2,"");
3033 p = root1;
3034 p2 = root2;
3035 while (*p2) {
3036 if (*p2 == '?') {
3037 *p2 = *p;
3038 p2++;
3039 } else {
3040 p2++;
3042 if (*p) p++;
3045 p = ext1;
3046 p2 = ext2;
3047 while (*p2) {
3048 if (*p2 == '?') {
3049 *p2 = *p;
3050 p2++;
3051 } else {
3052 p2++;
3054 if (*p) p++;
3057 pstrcpy(name2,root2);
3058 if (ext2[0]) {
3059 pstrcat(name2,".");
3060 pstrcat(name2,ext2);
3063 return(True);
3066 /*******************************************************************
3067 check if a user is allowed to rename a file
3068 ********************************************************************/
3069 static BOOL can_rename(char *fname,connection_struct *conn)
3071 SMB_STRUCT_STAT sbuf;
3073 if (!CAN_WRITE(conn)) return(False);
3075 if (dos_lstat(fname,&sbuf) != 0) return(False);
3076 if (!check_file_sharing(conn,fname,True)) return(False);
3078 return(True);
3081 /****************************************************************************
3082 The guts of the rename command, split out so it may be called by the NT SMB
3083 code.
3084 ****************************************************************************/
3085 int rename_internals(connection_struct *conn,
3086 char *inbuf, char *outbuf, char *name,
3087 char *newname, BOOL replace_if_exists)
3089 pstring directory;
3090 pstring mask;
3091 pstring newname_last_component;
3092 char *p;
3093 BOOL has_wild;
3094 BOOL bad_path1 = False;
3095 BOOL bad_path2 = False;
3096 int count=0;
3097 int error = ERRnoaccess;
3098 BOOL exists=False;
3100 *directory = *mask = 0;
3102 unix_convert(name,conn,0,&bad_path1,NULL);
3103 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3106 * Split the old name into directory and last component
3107 * strings. Note that unix_convert may have stripped off a
3108 * leading ./ from both name and newname if the rename is
3109 * at the root of the share. We need to make sure either both
3110 * name and newname contain a / character or neither of them do
3111 * as this is checked in resolve_wildcards().
3114 p = strrchr(name,'/');
3115 if (!p) {
3116 pstrcpy(directory,".");
3117 pstrcpy(mask,name);
3118 } else {
3119 *p = 0;
3120 pstrcpy(directory,name);
3121 pstrcpy(mask,p+1);
3122 *p = '/'; /* Replace needed for exceptional test below. */
3125 if (is_mangled(mask))
3126 check_mangled_cache( mask );
3128 has_wild = strchr(mask,'*') || strchr(mask,'?');
3130 if (!has_wild) {
3132 * No wildcards - just process the one file.
3134 BOOL is_short_name = is_8_3(name, True);
3136 /* Add a terminating '/' to the directory name. */
3137 pstrcat(directory,"/");
3138 pstrcat(directory,mask);
3140 /* Ensure newname contains a '/' also */
3141 if(strrchr(newname,'/') == 0) {
3142 pstring tmpstr;
3144 pstrcpy(tmpstr, "./");
3145 pstrcat(tmpstr, newname);
3146 pstrcpy(newname, tmpstr);
3149 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",
3150 case_sensitive, case_preserve, short_case_preserve, directory,
3151 newname, newname_last_component, is_short_name));
3154 * Check for special case with case preserving and not
3155 * case sensitive, if directory and newname are identical,
3156 * and the old last component differs from the original
3157 * last component only by case, then we should allow
3158 * the rename (user is trying to change the case of the
3159 * filename).
3161 if((case_sensitive == False) &&
3162 (((case_preserve == True) &&
3163 (is_short_name == False)) ||
3164 ((short_case_preserve == True) &&
3165 (is_short_name == True))) &&
3166 strcsequal(directory, newname)) {
3167 pstring newname_modified_last_component;
3170 * Get the last component of the modified name.
3171 * Note that we guarantee that newname contains a '/'
3172 * character above.
3174 p = strrchr(newname,'/');
3175 pstrcpy(newname_modified_last_component,p+1);
3177 if(strcsequal(newname_modified_last_component,
3178 newname_last_component) == False) {
3180 * Replace the modified last component with
3181 * the original.
3183 pstrcpy(p+1, newname_last_component);
3187 if(replace_if_exists) {
3189 * NT SMB specific flag - rename can overwrite
3190 * file with the same name so don't check for
3191 * file_exist().
3193 if(resolve_wildcards(directory,newname) &&
3194 can_rename(directory,conn) &&
3195 !dos_rename(directory,newname))
3196 count++;
3197 } else {
3198 if (resolve_wildcards(directory,newname) &&
3199 can_rename(directory,conn) &&
3200 !file_exist(newname,NULL) &&
3201 !dos_rename(directory,newname))
3202 count++;
3205 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3206 directory,newname));
3208 if (!count) exists = file_exist(directory,NULL);
3209 if (!count && exists && file_exist(newname,NULL)) {
3210 exists = True;
3211 error = 183;
3213 } else {
3215 * Wildcards - process each file that matches.
3217 void *dirptr = NULL;
3218 char *dname;
3219 pstring destname;
3221 if (check_name(directory,conn))
3222 dirptr = OpenDir(conn, directory, True);
3224 if (dirptr) {
3225 error = ERRbadfile;
3227 if (strequal(mask,"????????.???"))
3228 pstrcpy(mask,"*");
3230 while ((dname = ReadDirName(dirptr))) {
3231 pstring fname;
3232 pstrcpy(fname,dname);
3234 if(!mask_match(fname, mask, case_sensitive, False))
3235 continue;
3237 error = ERRnoaccess;
3238 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3239 if (!can_rename(fname,conn)) {
3240 DEBUG(6,("rename %s refused\n", fname));
3241 continue;
3243 pstrcpy(destname,newname);
3245 if (!resolve_wildcards(fname,destname)) {
3246 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3247 continue;
3250 if (!replace_if_exists && file_exist(destname,NULL)) {
3251 DEBUG(6,("file_exist %s\n", destname));
3252 error = 183;
3253 continue;
3256 if (!dos_rename(fname,destname))
3257 count++;
3258 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3260 CloseDir(dirptr);
3264 if (count == 0) {
3265 if (exists)
3266 return(ERROR(ERRDOS,error));
3267 else {
3268 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3269 unix_ERR_class = ERRDOS;
3270 unix_ERR_code = ERRbadpath;
3272 return(UNIXERROR(ERRDOS,error));
3276 return 0;
3279 /****************************************************************************
3280 Reply to a mv.
3281 ****************************************************************************/
3283 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3285 int outsize = 0;
3286 pstring name;
3287 pstring newname;
3289 pstrcpy(name,smb_buf(inbuf) + 1);
3290 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3292 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3294 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3295 if(outsize == 0)
3296 outsize = set_message(outbuf,0,0,True);
3298 return(outsize);
3301 /*******************************************************************
3302 copy a file as part of a reply_copy
3303 ******************************************************************/
3304 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3305 int count,BOOL target_is_directory)
3307 int Access,action;
3308 SMB_STRUCT_STAT st;
3309 int ret=0;
3310 files_struct *fsp1,*fsp2;
3311 pstring dest;
3313 pstrcpy(dest,dest1);
3314 if (target_is_directory) {
3315 char *p = strrchr(src,'/');
3316 if (p)
3317 p++;
3318 else
3319 p = src;
3320 pstrcat(dest,"/");
3321 pstrcat(dest,p);
3324 if (!file_exist(src,&st)) return(False);
3326 fsp1 = file_new();
3327 if (!fsp1) return(False);
3328 open_file_shared(fsp1,conn,src,(DENY_NONE<<4),
3329 1,0,0,&Access,&action);
3331 if (!fsp1->open) {
3332 file_free(fsp1);
3333 return(False);
3336 if (!target_is_directory && count)
3337 ofun = 1;
3339 fsp2 = file_new();
3340 if (!fsp2) {
3341 close_file(fsp1,False);
3342 return(False);
3344 open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1,
3345 ofun,st.st_mode,0,&Access,&action);
3347 if (!fsp2->open) {
3348 close_file(fsp1,False);
3349 file_free(fsp2);
3350 return(False);
3353 if ((ofun&3) == 1) {
3354 sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END);
3357 if (st.st_size)
3358 ret = transfer_file(fsp1->fd_ptr->fd,
3359 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3361 close_file(fsp1,False);
3362 close_file(fsp2,False);
3364 return(ret == st.st_size);
3369 /****************************************************************************
3370 reply to a file copy.
3371 ****************************************************************************/
3372 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3374 int outsize = 0;
3375 pstring name;
3376 pstring directory;
3377 pstring mask,newname;
3378 char *p;
3379 int count=0;
3380 int error = ERRnoaccess;
3381 BOOL has_wild;
3382 BOOL exists=False;
3383 int tid2 = SVAL(inbuf,smb_vwv0);
3384 int ofun = SVAL(inbuf,smb_vwv1);
3385 int flags = SVAL(inbuf,smb_vwv2);
3386 BOOL target_is_directory=False;
3387 BOOL bad_path1 = False;
3388 BOOL bad_path2 = False;
3390 *directory = *mask = 0;
3392 pstrcpy(name,smb_buf(inbuf));
3393 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3395 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3397 if (tid2 != conn->cnum) {
3398 /* can't currently handle inter share copies XXXX */
3399 DEBUG(3,("Rejecting inter-share copy\n"));
3400 return(ERROR(ERRSRV,ERRinvdevice));
3403 unix_convert(name,conn,0,&bad_path1,NULL);
3404 unix_convert(newname,conn,0,&bad_path2,NULL);
3406 target_is_directory = directory_exist(newname,NULL);
3408 if ((flags&1) && target_is_directory) {
3409 return(ERROR(ERRDOS,ERRbadfile));
3412 if ((flags&2) && !target_is_directory) {
3413 return(ERROR(ERRDOS,ERRbadpath));
3416 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3417 /* wants a tree copy! XXXX */
3418 DEBUG(3,("Rejecting tree copy\n"));
3419 return(ERROR(ERRSRV,ERRerror));
3422 p = strrchr(name,'/');
3423 if (!p) {
3424 pstrcpy(directory,"./");
3425 pstrcpy(mask,name);
3426 } else {
3427 *p = 0;
3428 pstrcpy(directory,name);
3429 pstrcpy(mask,p+1);
3432 if (is_mangled(mask))
3433 check_mangled_cache( mask );
3435 has_wild = strchr(mask,'*') || strchr(mask,'?');
3437 if (!has_wild) {
3438 pstrcat(directory,"/");
3439 pstrcat(directory,mask);
3440 if (resolve_wildcards(directory,newname) &&
3441 copy_file(directory,newname,conn,ofun,
3442 count,target_is_directory)) count++;
3443 if (!count) exists = file_exist(directory,NULL);
3444 } else {
3445 void *dirptr = NULL;
3446 char *dname;
3447 pstring destname;
3449 if (check_name(directory,conn))
3450 dirptr = OpenDir(conn, directory, True);
3452 if (dirptr)
3454 error = ERRbadfile;
3456 if (strequal(mask,"????????.???"))
3457 pstrcpy(mask,"*");
3459 while ((dname = ReadDirName(dirptr)))
3461 pstring fname;
3462 pstrcpy(fname,dname);
3464 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3466 error = ERRnoaccess;
3467 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3468 pstrcpy(destname,newname);
3469 if (resolve_wildcards(fname,destname) &&
3470 copy_file(directory,newname,conn,ofun,
3471 count,target_is_directory)) count++;
3472 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3474 CloseDir(dirptr);
3478 if (count == 0) {
3479 if (exists)
3480 return(ERROR(ERRDOS,error));
3481 else
3483 if((errno == ENOENT) && (bad_path1 || bad_path2))
3485 unix_ERR_class = ERRDOS;
3486 unix_ERR_code = ERRbadpath;
3488 return(UNIXERROR(ERRDOS,error));
3492 outsize = set_message(outbuf,1,0,True);
3493 SSVAL(outbuf,smb_vwv0,count);
3495 return(outsize);
3498 /****************************************************************************
3499 reply to a setdir
3500 ****************************************************************************/
3501 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3503 int snum;
3504 int outsize = 0;
3505 BOOL ok = False;
3506 pstring newdir;
3508 snum = SNUM(conn);
3509 if (!CAN_SETDIR(snum))
3510 return(ERROR(ERRDOS,ERRnoaccess));
3512 pstrcpy(newdir,smb_buf(inbuf) + 1);
3513 strlower(newdir);
3515 if (strlen(newdir) == 0) {
3516 ok = True;
3517 } else {
3518 ok = directory_exist(newdir,NULL);
3519 if (ok) {
3520 string_set(&conn->connectpath,newdir);
3524 if (!ok)
3525 return(ERROR(ERRDOS,ERRbadpath));
3527 outsize = set_message(outbuf,0,0,True);
3528 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3530 DEBUG(3,("setdir %s\n", newdir));
3532 return(outsize);
3535 /****************************************************************************
3536 reply to a lockingX request
3537 ****************************************************************************/
3538 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3540 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3541 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3542 #if 0
3543 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3544 #endif
3545 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3546 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3547 SMB_OFF_T count = 0, offset = 0;
3548 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3549 int i;
3550 char *data;
3551 uint32 ecode=0, dummy2;
3552 int eclass=0, dummy1;
3553 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3554 CHECK_FSP(fsp,conn);
3555 CHECK_ERROR(fsp);
3557 data = smb_buf(inbuf);
3559 /* Check if this is an oplock break on a file
3560 we have granted an oplock on.
3562 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3564 int token;
3565 SMB_DEV_T dev = fsp->fd_ptr->dev;
3566 SMB_INO_T inode = fsp->fd_ptr->inode;
3568 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3569 fsp->fnum));
3571 * Make sure we have granted an oplock on this file.
3573 if(!fsp->granted_oplock)
3575 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3576 no oplock granted on this file.\n", fsp->fnum));
3577 return ERROR(ERRDOS,ERRlock);
3580 /* Remove the oplock flag from the sharemode. */
3581 lock_share_entry(fsp->conn, dev, inode, &token);
3582 if(remove_share_oplock(fsp, token)==False) {
3584 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3585 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3587 unlock_share_entry(fsp->conn, dev, inode, token);
3588 } else {
3589 unlock_share_entry(fsp->conn, dev, inode, token);
3591 /* Clear the granted flag and return. */
3592 fsp->granted_oplock = False;
3595 /* if this is a pure oplock break request then don't send a reply */
3596 if (num_locks == 0 && num_ulocks == 0)
3598 /* Sanity check - ensure a pure oplock break is not a
3599 chained request. */
3600 if(CVAL(inbuf,smb_vwv0) != 0xff)
3601 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3602 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3603 return -1;
3607 /* Data now points at the beginning of the list
3608 of smb_unlkrng structs */
3609 for(i = 0; i < (int)num_ulocks; i++) {
3610 if(!large_file_format) {
3611 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3612 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3614 #ifdef LARGE_SMB_OFF_T
3615 else {
3616 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3617 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3618 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3619 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3621 #endif /* LARGE_SMB_OFF_T */
3623 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3624 (double)offset, (double)count, fsp->fsp_name ));
3626 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3627 return ERROR(eclass,ecode);
3630 /* Setup the timeout in seconds. */
3631 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3633 /* Now do any requested locks */
3634 data += ((large_file_format ? 20 : 10)*num_ulocks);
3636 /* Data now points at the beginning of the list
3637 of smb_lkrng structs */
3639 for(i = 0; i < (int)num_locks; i++) {
3640 if(!large_file_format) {
3641 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3642 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3644 #ifdef LARGE_SMB_OFF_T
3645 else {
3646 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3647 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3648 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3649 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3651 #endif /* LARGE_SMB_OFF_T */
3653 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3654 (double)offset, (double)count, fsp->fsp_name ));
3656 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3657 &eclass, &ecode)) {
3658 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3660 * A blocking lock was requested. Package up
3661 * this smb into a queued request and push it
3662 * onto the blocking lock queue.
3664 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3665 return -1;
3667 break;
3671 /* If any of the above locks failed, then we must unlock
3672 all of the previous locks (X/Open spec). */
3673 if(i != num_locks && num_locks != 0) {
3674 for(; i >= 0; i--) {
3675 if(!large_file_format) {
3676 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3677 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3679 #ifdef LARGE_SMB_OFF_T
3680 else {
3681 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3682 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3683 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3684 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3686 #endif /* LARGE_SMB_OFF_T */
3688 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3690 return ERROR(eclass,ecode);
3693 set_message(outbuf,2,0,True);
3695 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3696 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3698 return chain_reply(inbuf,outbuf,length,bufsize);
3702 /****************************************************************************
3703 reply to a SMBreadbmpx (read block multiplex) request
3704 ****************************************************************************/
3705 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3707 ssize_t nread = -1;
3708 ssize_t total_read;
3709 char *data;
3710 SMB_OFF_T startpos;
3711 int outsize;
3712 size_t maxcount;
3713 int max_per_packet;
3714 size_t tcount;
3715 int pad;
3716 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3718 /* this function doesn't seem to work - disable by default */
3719 if (!lp_readbmpx())
3720 return(ERROR(ERRSRV,ERRuseSTD));
3722 outsize = set_message(outbuf,8,0,True);
3724 CHECK_FSP(fsp,conn);
3725 CHECK_READ(fsp);
3726 CHECK_ERROR(fsp);
3728 startpos = IVAL(inbuf,smb_vwv1);
3729 maxcount = SVAL(inbuf,smb_vwv3);
3731 data = smb_buf(outbuf);
3732 pad = ((long)data)%4;
3733 if (pad) pad = 4 - pad;
3734 data += pad;
3736 max_per_packet = bufsize-(outsize+pad);
3737 tcount = maxcount;
3738 total_read = 0;
3740 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3741 return(ERROR(ERRDOS,ERRlock));
3745 size_t N = MIN(max_per_packet,tcount-total_read);
3747 nread = read_file(fsp,data,startpos,N);
3749 if (nread <= 0) nread = 0;
3751 if (nread < (ssize_t)N)
3752 tcount = total_read + nread;
3754 set_message(outbuf,8,nread,False);
3755 SIVAL(outbuf,smb_vwv0,startpos);
3756 SSVAL(outbuf,smb_vwv2,tcount);
3757 SSVAL(outbuf,smb_vwv6,nread);
3758 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3760 send_smb(Client,outbuf);
3762 total_read += nread;
3763 startpos += nread;
3765 while (total_read < (ssize_t)tcount);
3767 return(-1);
3770 /****************************************************************************
3771 reply to a SMBwritebmpx (write block multiplex primary) request
3772 ****************************************************************************/
3773 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3775 size_t numtowrite;
3776 ssize_t nwritten = -1;
3777 int outsize = 0;
3778 SMB_OFF_T startpos;
3779 size_t tcount;
3780 BOOL write_through;
3781 int smb_doff;
3782 char *data;
3783 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3785 CHECK_FSP(fsp,conn);
3786 CHECK_WRITE(fsp);
3787 CHECK_ERROR(fsp);
3789 tcount = SVAL(inbuf,smb_vwv1);
3790 startpos = IVAL(inbuf,smb_vwv3);
3791 write_through = BITSETW(inbuf+smb_vwv7,0);
3792 numtowrite = SVAL(inbuf,smb_vwv10);
3793 smb_doff = SVAL(inbuf,smb_vwv11);
3795 data = smb_base(inbuf) + smb_doff;
3797 /* If this fails we need to send an SMBwriteC response,
3798 not an SMBwritebmpx - set this up now so we don't forget */
3799 CVAL(outbuf,smb_com) = SMBwritec;
3801 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3802 return(ERROR(ERRDOS,ERRlock));
3804 seek_file(fsp,startpos);
3805 nwritten = write_file(fsp,data,numtowrite);
3807 if(lp_syncalways(SNUM(conn)) || write_through)
3808 sync_file(conn,fsp);
3810 if(nwritten < (ssize_t)numtowrite)
3811 return(UNIXERROR(ERRHRD,ERRdiskfull));
3813 /* If the maximum to be written to this file
3814 is greater than what we just wrote then set
3815 up a secondary struct to be attached to this
3816 fd, we will use this to cache error messages etc. */
3817 if((ssize_t)tcount > nwritten)
3819 write_bmpx_struct *wbms;
3820 if(fsp->wbmpx_ptr != NULL)
3821 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3822 else
3823 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3824 if(!wbms)
3826 DEBUG(0,("Out of memory in reply_readmpx\n"));
3827 return(ERROR(ERRSRV,ERRnoresource));
3829 wbms->wr_mode = write_through;
3830 wbms->wr_discard = False; /* No errors yet */
3831 wbms->wr_total_written = nwritten;
3832 wbms->wr_errclass = 0;
3833 wbms->wr_error = 0;
3834 fsp->wbmpx_ptr = wbms;
3837 /* We are returning successfully, set the message type back to
3838 SMBwritebmpx */
3839 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3841 outsize = set_message(outbuf,1,0,True);
3843 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3845 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3846 fsp->fnum, numtowrite, nwritten ) );
3848 if (write_through && tcount==nwritten) {
3849 /* we need to send both a primary and a secondary response */
3850 smb_setlen(outbuf,outsize - 4);
3851 send_smb(Client,outbuf);
3853 /* now the secondary */
3854 outsize = set_message(outbuf,1,0,True);
3855 CVAL(outbuf,smb_com) = SMBwritec;
3856 SSVAL(outbuf,smb_vwv0,nwritten);
3859 return(outsize);
3863 /****************************************************************************
3864 reply to a SMBwritebs (write block multiplex secondary) request
3865 ****************************************************************************/
3866 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3868 size_t numtowrite;
3869 ssize_t nwritten = -1;
3870 int outsize = 0;
3871 SMB_OFF_T startpos;
3872 size_t tcount;
3873 BOOL write_through;
3874 int smb_doff;
3875 char *data;
3876 write_bmpx_struct *wbms;
3877 BOOL send_response = False;
3878 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3880 CHECK_FSP(fsp,conn);
3881 CHECK_WRITE(fsp);
3883 tcount = SVAL(inbuf,smb_vwv1);
3884 startpos = IVAL(inbuf,smb_vwv2);
3885 numtowrite = SVAL(inbuf,smb_vwv6);
3886 smb_doff = SVAL(inbuf,smb_vwv7);
3888 data = smb_base(inbuf) + smb_doff;
3890 /* We need to send an SMBwriteC response, not an SMBwritebs */
3891 CVAL(outbuf,smb_com) = SMBwritec;
3893 /* This fd should have an auxiliary struct attached,
3894 check that it does */
3895 wbms = fsp->wbmpx_ptr;
3896 if(!wbms) return(-1);
3898 /* If write through is set we can return errors, else we must
3899 cache them */
3900 write_through = wbms->wr_mode;
3902 /* Check for an earlier error */
3903 if(wbms->wr_discard)
3904 return -1; /* Just discard the packet */
3906 seek_file(fsp,startpos);
3907 nwritten = write_file(fsp,data,numtowrite);
3909 if(lp_syncalways(SNUM(conn)) || write_through)
3910 sync_file(conn,fsp);
3912 if (nwritten < (ssize_t)numtowrite)
3914 if(write_through)
3916 /* We are returning an error - we can delete the aux struct */
3917 if (wbms) free((char *)wbms);
3918 fsp->wbmpx_ptr = NULL;
3919 return(ERROR(ERRHRD,ERRdiskfull));
3921 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3924 /* Increment the total written, if this matches tcount
3925 we can discard the auxiliary struct (hurrah !) and return a writeC */
3926 wbms->wr_total_written += nwritten;
3927 if(wbms->wr_total_written >= tcount)
3929 if (write_through)
3931 outsize = set_message(outbuf,1,0,True);
3932 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3933 send_response = True;
3936 free((char *)wbms);
3937 fsp->wbmpx_ptr = NULL;
3940 if(send_response)
3941 return(outsize);
3943 return(-1);
3947 /****************************************************************************
3948 reply to a SMBsetattrE
3949 ****************************************************************************/
3950 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3952 struct utimbuf unix_times;
3953 int outsize = 0;
3954 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3956 outsize = set_message(outbuf,0,0,True);
3958 CHECK_FSP(fsp,conn);
3959 CHECK_ERROR(fsp);
3961 /* Convert the DOS times into unix times. Ignore create
3962 time as UNIX can't set this.
3964 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3965 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3968 * Patch from Ray Frush <frush@engr.colostate.edu>
3969 * Sometimes times are sent as zero - ignore them.
3972 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3974 /* Ignore request */
3975 if( DEBUGLVL( 3 ) )
3977 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
3978 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
3980 return(outsize);
3982 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3984 /* set modify time = to access time if modify time was 0 */
3985 unix_times.modtime = unix_times.actime;
3988 /* Set the date on this file */
3989 if(file_utime(conn, fsp->fsp_name, &unix_times))
3990 return(ERROR(ERRDOS,ERRnoaccess));
3992 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
3993 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
3995 return(outsize);
3999 /****************************************************************************
4000 reply to a SMBgetattrE
4001 ****************************************************************************/
4002 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4004 SMB_STRUCT_STAT sbuf;
4005 int outsize = 0;
4006 int mode;
4007 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4009 outsize = set_message(outbuf,11,0,True);
4011 CHECK_FSP(fsp,conn);
4012 CHECK_ERROR(fsp);
4014 /* Do an fstat on this file */
4015 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4016 return(UNIXERROR(ERRDOS,ERRnoaccess));
4018 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4020 /* Convert the times into dos times. Set create
4021 date to be last modify date as UNIX doesn't save
4022 this */
4023 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4024 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4025 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4026 if (mode & aDIR)
4028 SIVAL(outbuf,smb_vwv6,0);
4029 SIVAL(outbuf,smb_vwv8,0);
4031 else
4033 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4034 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
4036 SSVAL(outbuf,smb_vwv10, mode);
4038 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4040 return(outsize);