changed find_free_file() to file_new().
[Samba/gbeck.git] / source / smbd / reply.c
blob340602d3a5c121026e3c5265044a40564ab363bd
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 files_struct *chain_fsp;
37 extern char magic_char;
38 extern BOOL case_sensitive;
39 extern BOOL case_preserve;
40 extern BOOL short_case_preserve;
41 extern pstring sesssetup_user;
42 extern fstring global_myworkgroup;
43 extern int Client;
44 extern int global_oplock_break;
46 /****************************************************************************
47 report a possible attack via the password buffer overflow bug
48 ****************************************************************************/
49 static void overflow_attack(int len)
51 if( DEBUGLVL( 0 ) )
53 dbgtext( "ERROR: Invalid password length %d.\n", len );
54 dbgtext( "Your machine may be under attack by someone " );
55 dbgtext( "attempting to exploit an old bug.\n" );
56 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
58 exit_server("possible attack");
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
65 int reply_special(char *inbuf,char *outbuf)
67 int outsize = 4;
68 int msg_type = CVAL(inbuf,0);
69 int msg_flags = CVAL(inbuf,1);
70 pstring name1,name2;
71 extern fstring remote_machine;
72 extern fstring local_machine;
73 int len;
74 char name_type = 0;
76 *name1 = *name2 = 0;
78 bzero(outbuf,smb_size);
80 smb_setlen(outbuf,0);
82 switch (msg_type) {
83 case 0x81: /* session request */
84 CVAL(outbuf,0) = 0x82;
85 CVAL(outbuf,3) = 0;
86 if (name_len(inbuf+4) > 50 ||
87 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
88 DEBUG(0,("Invalid name length in session request\n"));
89 return(0);
91 name_extract(inbuf,4,name1);
92 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
93 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
94 name1,name2));
96 fstrcpy(remote_machine,name2);
97 remote_machine[15] = 0;
98 trim_string(remote_machine," "," ");
99 strlower(remote_machine);
101 fstrcpy(local_machine,name1);
102 len = strlen(local_machine);
103 if (len == 16) {
104 name_type = local_machine[15];
105 local_machine[15] = 0;
107 trim_string(local_machine," "," ");
108 strlower(local_machine);
110 if (name_type == 'R') {
111 /* We are being asked for a pathworks session ---
112 no thanks! */
113 CVAL(outbuf, 0) = 0x83;
114 break;
117 add_session_user(remote_machine);
119 reload_services(True);
120 reopen_logs();
122 if (lp_status(-1)) {
123 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
126 break;
128 case 0x89: /* session keepalive request
129 (some old clients produce this?) */
130 CVAL(outbuf,0) = 0x85;
131 CVAL(outbuf,3) = 0;
132 break;
134 case 0x82: /* positive session response */
135 case 0x83: /* negative session response */
136 case 0x84: /* retarget session response */
137 DEBUG(0,("Unexpected session response\n"));
138 break;
140 case 0x85: /* session keepalive */
141 default:
142 return(0);
145 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
146 msg_type, msg_flags));
148 return(outsize);
152 /*******************************************************************
153 work out what error to give to a failed connection
154 ********************************************************************/
155 static int connection_error(char *inbuf,char *outbuf,int ecode)
157 if (ecode == ERRnoipc) {
158 return(ERROR(ERRDOS,ERRnoipc));
161 return(ERROR(ERRSRV,ecode));
166 /****************************************************************************
167 parse a share descriptor string
168 ****************************************************************************/
169 static void parse_connect(char *p,char *service,char *user,
170 char *password,int *pwlen,char *dev)
172 char *p2;
174 DEBUG(4,("parsing connect string %s\n",p));
176 p2 = strrchr(p,'\\');
177 if (p2 == NULL)
178 fstrcpy(service,p);
179 else
180 fstrcpy(service,p2+1);
182 p += strlen(p) + 2;
184 fstrcpy(password,p);
185 *pwlen = strlen(password);
187 p += strlen(p) + 2;
189 fstrcpy(dev,p);
191 *user = 0;
192 p = strchr(service,'%');
193 if (p != NULL)
195 *p = 0;
196 fstrcpy(user,p+1);
203 /****************************************************************************
204 reply to a tcon
205 ****************************************************************************/
206 int reply_tcon(connection_struct *conn,
207 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
209 pstring service;
210 pstring user;
211 pstring password;
212 pstring dev;
213 int outsize = 0;
214 uint16 vuid = SVAL(inbuf,smb_uid);
215 int pwlen=0;
216 int ecode = -1;
218 *service = *user = *password = *dev = 0;
220 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
223 * Pass the user through the NT -> unix user mapping
224 * function.
227 (void)map_username(user);
230 * Do any UNIX username case mangling.
232 (void)Get_Pwnam( user, True);
234 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
236 if (!conn) {
237 return(connection_error(inbuf,outbuf,ecode));
240 outsize = set_message(outbuf,2,0,True);
241 SSVAL(outbuf,smb_vwv0,max_recv);
242 SSVAL(outbuf,smb_vwv1,conn->cnum);
243 SSVAL(outbuf,smb_tid,conn->cnum);
245 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
246 service, user, conn->cnum));
248 return(outsize);
252 /****************************************************************************
253 reply to a tcon and X
254 ****************************************************************************/
255 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
257 pstring service;
258 pstring user;
259 pstring password;
260 pstring devicename;
261 int ecode = -1;
262 uint16 vuid = SVAL(inbuf,smb_uid);
263 int passlen = SVAL(inbuf,smb_vwv3);
264 char *path;
265 char *p;
267 *service = *user = *password = *devicename = 0;
269 /* we might have to close an old one */
270 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
271 close_cnum(conn,vuid);
274 if (passlen > MAX_PASS_LEN) {
275 overflow_attack(passlen);
278 memcpy(password,smb_buf(inbuf),passlen);
279 password[passlen]=0;
280 path = smb_buf(inbuf) + passlen;
282 if (passlen != 24) {
283 if (strequal(password," "))
284 *password = 0;
285 passlen = strlen(password);
288 fstrcpy(service,path+2);
289 p = strchr(service,'\\');
290 if (!p)
291 return(ERROR(ERRSRV,ERRinvnetname));
292 *p = 0;
293 fstrcpy(service,p+1);
294 p = strchr(service,'%');
295 if (p) {
296 *p++ = 0;
297 fstrcpy(user,p);
299 StrnCpy(devicename,path + strlen(path) + 1,6);
300 DEBUG(4,("Got device type %s\n",devicename));
303 * Pass the user through the NT -> unix user mapping
304 * function.
307 (void)map_username(user);
310 * Do any UNIX username case mangling.
312 (void)Get_Pwnam(user, True);
314 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
316 if (!conn)
317 return(connection_error(inbuf,outbuf,ecode));
319 if (Protocol < PROTOCOL_NT1) {
320 set_message(outbuf,2,strlen(devicename)+1,True);
321 pstrcpy(smb_buf(outbuf),devicename);
322 } else {
323 char *fsname = FSTYPE_STRING;
325 set_message(outbuf,3,3,True);
327 p = smb_buf(outbuf);
328 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
329 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
331 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
333 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
336 DEBUG(3,("tconX service=%s user=%s\n",
337 service, user));
339 /* set the incoming and outgoing tid to the just created one */
340 SSVAL(inbuf,smb_tid,conn->cnum);
341 SSVAL(outbuf,smb_tid,conn->cnum);
343 return chain_reply(inbuf,outbuf,length,bufsize);
347 /****************************************************************************
348 reply to an unknown type
349 ****************************************************************************/
350 int reply_unknown(char *inbuf,char *outbuf)
352 int type;
353 type = CVAL(inbuf,smb_com);
355 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
356 smb_fn_name(type), type, type));
358 return(ERROR(ERRSRV,ERRunknownsmb));
362 /****************************************************************************
363 reply to an ioctl
364 ****************************************************************************/
365 int reply_ioctl(connection_struct *conn,
366 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
368 DEBUG(3,("ignoring ioctl\n"));
369 #if 0
370 /* we just say it succeeds and hope its all OK.
371 some day it would be nice to interpret them individually */
372 return set_message(outbuf,1,0,True);
373 #else
374 return(ERROR(ERRSRV,ERRnosupport));
375 #endif
378 /****************************************************************************
379 always return an error: it's just a matter of which one...
380 ****************************************************************************/
381 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
382 char *smb_passwd, int smb_passlen,
383 char *smb_nt_passwd, int smb_nt_passlen)
385 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
386 if (lp_security() == SEC_USER)
388 smb_trust_acct = getsmbpwnam(user);
390 else
392 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
393 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
394 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
397 if (smb_trust_acct == NULL)
399 /* lkclXXXX: workstation entry doesn't exist */
400 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
401 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
402 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
404 else
406 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
408 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
409 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
410 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
413 if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
415 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
416 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
417 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
420 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
422 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
423 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
424 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
427 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
429 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
430 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
431 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
434 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
436 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
437 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
438 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
442 /* don't know what to do: indicate logon failure */
443 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
444 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
448 /****************************************************************************
449 reply to a session setup command
450 ****************************************************************************/
451 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
453 uint16 sess_vuid;
454 int gid;
455 int uid;
456 int smb_bufsize;
457 int smb_mpxmax;
458 int smb_vc_num;
459 uint32 smb_sesskey;
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);
476 smb_mpxmax = SVAL(inbuf,smb_vwv3);
477 smb_vc_num = SVAL(inbuf,smb_vwv4);
478 smb_sesskey = IVAL(inbuf,smb_vwv5);
480 if (Protocol < PROTOCOL_NT1) {
481 smb_apasslen = SVAL(inbuf,smb_vwv7);
482 if (smb_apasslen > MAX_PASS_LEN)
484 overflow_attack(smb_apasslen);
487 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
488 smb_apasswd[smb_apasslen] = 0;
489 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
491 if (!doencrypt && (lp_security() != SEC_SERVER)) {
492 smb_apasslen = strlen(smb_apasswd);
494 } else {
495 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
496 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
497 uint32 client_caps = IVAL(inbuf,smb_vwv11);
498 enum remote_arch_types ra_type = get_remote_arch();
500 char *p = smb_buf(inbuf);
502 /* client_caps is used as final determination if client is NT or Win95.
503 This is needed to return the correct error codes in some
504 circumstances.
507 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
509 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
510 set_remote_arch( RA_WINNT);
511 else
512 set_remote_arch( RA_WIN95);
515 if (passlen1 != 24 && passlen2 != 24)
516 doencrypt = False;
518 if (passlen1 > MAX_PASS_LEN) {
519 overflow_attack(passlen1);
522 passlen1 = MIN(passlen1, MAX_PASS_LEN);
523 passlen2 = MIN(passlen2, MAX_PASS_LEN);
525 if(!doencrypt) {
526 /* both Win95 and WinNT stuff up the password lengths for
527 non-encrypting systems. Uggh.
529 if passlen1==24 its a win95 system, and its setting the
530 password length incorrectly. Luckily it still works with the
531 default code because Win95 will null terminate the password
532 anyway
534 if passlen1>0 and passlen2>0 then maybe its a NT box and its
535 setting passlen2 to some random value which really stuffs
536 things up. we need to fix that one. */
538 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
539 passlen2 = 0;
542 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
543 /* Save the lanman2 password and the NT md4 password. */
544 smb_apasslen = passlen1;
545 memcpy(smb_apasswd,p,smb_apasslen);
546 smb_apasswd[smb_apasslen] = 0;
547 smb_ntpasslen = passlen2;
548 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
549 smb_ntpasswd[smb_ntpasslen] = 0;
550 } else {
551 /* we use the first password that they gave */
552 smb_apasslen = passlen1;
553 StrnCpy(smb_apasswd,p,smb_apasslen);
555 /* trim the password */
556 smb_apasslen = strlen(smb_apasswd);
558 /* wfwg sometimes uses a space instead of a null */
559 if (strequal(smb_apasswd," ")) {
560 smb_apasslen = 0;
561 *smb_apasswd = 0;
565 p += passlen1 + passlen2;
566 fstrcpy(user,p); p = skip_string(p,1);
567 domain = p;
569 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
570 domain,skip_string(p,1),skip_string(p,2)));
574 DEBUG(3,("sesssetupX:name=[%s]\n",user));
576 /* If name ends in $ then I think it's asking about whether a */
577 /* computer with that name (minus the $) has access. For now */
578 /* say yes to everything ending in $. */
579 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
581 return session_trust_account(conn, inbuf, outbuf, user,
582 smb_apasswd, smb_apasslen,
583 smb_ntpasswd, smb_ntpasslen);
586 /* If no username is sent use the guest account */
587 if (!*user)
589 pstrcpy(user,lp_guestaccount(-1));
590 /* If no user and no password then set guest flag. */
591 if( *smb_apasswd == 0)
592 guest = True;
595 strlower(user);
598 * In share level security, only overwrite sesssetup_use if
599 * it's a non null-session share. Helps keep %U and %G
600 * working.
603 if((lp_security() != SEC_SHARE) || *user)
604 pstrcpy(sesssetup_user,user);
606 reload_services(True);
609 * Save the username before mapping. We will use
610 * the original username sent to us for security=server
611 * and security=domain checking.
614 pstrcpy( orig_user, user);
617 * Pass the user through the NT -> unix user mapping
618 * function.
621 (void)map_username(user);
624 * Do any UNIX username case mangling.
626 (void)Get_Pwnam( user, True);
628 add_session_user(user);
631 * Check if the given username was the guest user with no password.
634 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
635 guest = True;
637 if (!guest && !(lp_security() == SEC_SERVER &&
638 /* Check with orig_user for security=server and
639 security=domain. */
640 server_validate(orig_user, domain,
641 smb_apasswd, smb_apasslen,
642 smb_ntpasswd, smb_ntpasslen)) &&
643 !(lp_security() == SEC_DOMAIN &&
644 domain_client_validate(orig_user, domain,
645 smb_apasswd, smb_apasslen,
646 smb_ntpasswd, smb_ntpasslen)) &&
647 !check_hosts_equiv(user)
651 /* now check if it's a valid username/password */
652 /* If an NT password was supplied try and validate with that
653 first. This is superior as the passwords are mixed case
654 128 length unicode */
655 if(smb_ntpasslen)
657 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
658 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
659 else
660 valid_nt_password = True;
662 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
664 if (lp_security() >= SEC_USER) {
665 #if (GUEST_SESSSETUP == 0)
666 return(ERROR(ERRSRV,ERRbadpw));
667 #endif
668 #if (GUEST_SESSSETUP == 1)
669 if (Get_Pwnam(user,True))
670 return(ERROR(ERRSRV,ERRbadpw));
671 #endif
673 if (*smb_apasswd || !Get_Pwnam(user,True))
674 pstrcpy(user,lp_guestaccount(-1));
675 DEBUG(3,("Registered username %s for guest access\n",user));
676 guest = True;
680 if (!Get_Pwnam(user,True)) {
681 DEBUG(3,("No such user %s - using guest account\n",user));
682 pstrcpy(user,lp_guestaccount(-1));
683 guest = True;
686 if (!strequal(user,lp_guestaccount(-1)) &&
687 lp_servicenumber(user) < 0)
689 int homes = lp_servicenumber(HOMES_NAME);
690 char *home = get_home_dir(user);
691 if (homes >= 0 && home)
692 lp_add_home(user,homes,home);
696 /* it's ok - setup a reply */
697 if (Protocol < PROTOCOL_NT1) {
698 set_message(outbuf,3,0,True);
699 } else {
700 char *p;
701 set_message(outbuf,3,3,True);
702 p = smb_buf(outbuf);
703 pstrcpy(p,"Unix"); p = skip_string(p,1);
704 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
705 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
706 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
707 /* perhaps grab OS version here?? */
710 /* Set the correct uid in the outgoing and incoming packets
711 We will use this on future requests to determine which
712 user we should become.
715 struct passwd *pw = Get_Pwnam(user,False);
716 if (!pw) {
717 DEBUG(1,("Username %s is invalid on this system\n",user));
718 return(ERROR(ERRSRV,ERRbadpw));
720 gid = pw->pw_gid;
721 uid = pw->pw_uid;
724 if (guest)
725 SSVAL(outbuf,smb_vwv2,1);
727 /* register the name and uid as being validated, so further connections
728 to a uid can get through without a password, on the same VC */
729 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
731 SSVAL(outbuf,smb_uid,sess_vuid);
732 SSVAL(inbuf,smb_uid,sess_vuid);
734 if (!done_sesssetup)
735 max_send = MIN(max_send,smb_bufsize);
737 DEBUG(6,("Client requested max send size of %d\n", max_send));
739 done_sesssetup = True;
741 return chain_reply(inbuf,outbuf,length,bufsize);
745 /****************************************************************************
746 reply to a chkpth
747 ****************************************************************************/
748 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
750 int outsize = 0;
751 int mode;
752 pstring name;
753 BOOL ok = False;
754 BOOL bad_path = False;
756 pstrcpy(name,smb_buf(inbuf) + 1);
757 unix_convert(name,conn,0,&bad_path);
759 mode = SVAL(inbuf,smb_vwv0);
761 if (check_name(name,conn))
762 ok = directory_exist(name,NULL);
764 if (!ok)
766 /* We special case this - as when a Windows machine
767 is parsing a path is steps through the components
768 one at a time - if a component fails it expects
769 ERRbadpath, not ERRbadfile.
771 if(errno == ENOENT)
773 unix_ERR_class = ERRDOS;
774 unix_ERR_code = ERRbadpath;
777 #if 0
778 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
779 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
780 (get_remote_arch() == RA_WINNT))
782 unix_ERR_class = ERRDOS;
783 unix_ERR_code = ERRbaddirectory;
785 #endif
787 return(UNIXERROR(ERRDOS,ERRbadpath));
790 outsize = set_message(outbuf,0,0,True);
792 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
794 return(outsize);
798 /****************************************************************************
799 reply to a getatr
800 ****************************************************************************/
801 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
803 pstring fname;
804 int outsize = 0;
805 struct stat sbuf;
806 BOOL ok = False;
807 int mode=0;
808 uint32 size=0;
809 time_t mtime=0;
810 BOOL bad_path = False;
812 pstrcpy(fname,smb_buf(inbuf) + 1);
813 unix_convert(fname,conn,0,&bad_path);
815 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
816 under WfWg - weird! */
817 if (! (*fname))
819 mode = aHIDDEN | aDIR;
820 if (!CAN_WRITE(conn)) mode |= aRONLY;
821 size = 0;
822 mtime = 0;
823 ok = True;
825 else
826 if (check_name(fname,conn))
828 if (sys_stat(fname,&sbuf) == 0)
830 mode = dos_mode(conn,fname,&sbuf);
831 size = sbuf.st_size;
832 mtime = sbuf.st_mtime;
833 if (mode & aDIR)
834 size = 0;
835 ok = True;
837 else
838 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
841 if (!ok)
843 if((errno == ENOENT) && bad_path)
845 unix_ERR_class = ERRDOS;
846 unix_ERR_code = ERRbadpath;
849 return(UNIXERROR(ERRDOS,ERRbadfile));
852 outsize = set_message(outbuf,10,0,True);
854 SSVAL(outbuf,smb_vwv0,mode);
855 if(lp_dos_filetime_resolution(SNUM(conn)) )
856 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
857 else
858 put_dos_date3(outbuf,smb_vwv1,mtime);
859 SIVAL(outbuf,smb_vwv3,size);
861 if (Protocol >= PROTOCOL_NT1) {
862 char *p = strrchr(fname,'/');
863 uint16 flg2 = SVAL(outbuf,smb_flg2);
864 if (!p) p = fname;
865 if (!is_8_3(fname, True))
866 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
869 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, size ) );
871 return(outsize);
875 /****************************************************************************
876 reply to a setatr
877 ****************************************************************************/
878 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
880 pstring fname;
881 int outsize = 0;
882 BOOL ok=False;
883 int mode;
884 time_t mtime;
885 BOOL bad_path = False;
887 pstrcpy(fname,smb_buf(inbuf) + 1);
888 unix_convert(fname,conn,0,&bad_path);
890 mode = SVAL(inbuf,smb_vwv0);
891 mtime = make_unix_date3(inbuf+smb_vwv1);
893 if (directory_exist(fname,NULL))
894 mode |= aDIR;
895 if (check_name(fname,conn))
896 ok = (dos_chmod(conn,fname,mode,NULL) == 0);
897 if (ok)
898 ok = set_filetime(conn,fname,mtime);
900 if (!ok)
902 if((errno == ENOENT) && bad_path)
904 unix_ERR_class = ERRDOS;
905 unix_ERR_code = ERRbadpath;
908 return(UNIXERROR(ERRDOS,ERRnoaccess));
911 outsize = set_message(outbuf,0,0,True);
913 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
915 return(outsize);
919 /****************************************************************************
920 reply to a dskattr
921 ****************************************************************************/
922 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
924 int outsize = 0;
925 int dfree,dsize,bsize;
927 sys_disk_free(".",&bsize,&dfree,&dsize);
929 outsize = set_message(outbuf,5,0,True);
931 SSVAL(outbuf,smb_vwv0,dsize);
932 SSVAL(outbuf,smb_vwv1,bsize/512);
933 SSVAL(outbuf,smb_vwv2,512);
934 SSVAL(outbuf,smb_vwv3,dfree);
936 DEBUG(3,("dskattr dfree=%d\n", dfree));
938 return(outsize);
942 /****************************************************************************
943 reply to a search
944 Can be called from SMBsearch, SMBffirst or SMBfunique.
945 ****************************************************************************/
946 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
948 pstring mask;
949 pstring directory;
950 pstring fname;
951 int size,mode;
952 time_t date;
953 int dirtype;
954 int outsize = 0;
955 int numentries = 0;
956 BOOL finished = False;
957 int maxentries;
958 int i;
959 char *p;
960 BOOL ok = False;
961 int status_len;
962 char *path;
963 char status[21];
964 int dptr_num= -1;
965 BOOL check_descend = False;
966 BOOL expect_close = False;
967 BOOL can_open = True;
968 BOOL bad_path = False;
970 *mask = *directory = *fname = 0;
972 /* If we were called as SMBffirst then we must expect close. */
973 if(CVAL(inbuf,smb_com) == SMBffirst)
974 expect_close = True;
976 outsize = set_message(outbuf,1,3,True);
977 maxentries = SVAL(inbuf,smb_vwv0);
978 dirtype = SVAL(inbuf,smb_vwv1);
979 path = smb_buf(inbuf) + 1;
980 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
983 /* dirtype &= ~aDIR; */
985 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
988 if (status_len == 0)
990 pstring dir2;
992 pstrcpy(directory,smb_buf(inbuf)+1);
993 pstrcpy(dir2,smb_buf(inbuf)+1);
994 unix_convert(directory,conn,0,&bad_path);
995 unix_format(dir2);
997 if (!check_name(directory,conn))
998 can_open = False;
1000 p = strrchr(dir2,'/');
1001 if (p == NULL)
1003 pstrcpy(mask,dir2);
1004 *dir2 = 0;
1006 else
1008 *p = 0;
1009 pstrcpy(mask,p+1);
1012 p = strrchr(directory,'/');
1013 if (!p)
1014 *directory = 0;
1015 else
1016 *p = 0;
1018 if (strlen(directory) == 0)
1019 pstrcpy(directory,"./");
1020 bzero(status,21);
1021 CVAL(status,0) = dirtype;
1023 else
1025 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1026 memcpy(mask,status+1,11);
1027 mask[11] = 0;
1028 dirtype = CVAL(status,0) & 0x1F;
1029 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1030 if (!conn->dirptr)
1031 goto SearchEmpty;
1032 string_set(&conn->dirpath,dptr_path(dptr_num));
1033 if (!case_sensitive)
1034 strnorm(mask);
1037 /* turn strings of spaces into a . */
1039 trim_string(mask,NULL," ");
1040 if ((p = strrchr(mask,' ')))
1042 fstring ext;
1043 fstrcpy(ext,p+1);
1044 *p = 0;
1045 trim_string(mask,NULL," ");
1046 pstrcat(mask,".");
1047 pstrcat(mask,ext);
1051 /* Convert the formatted mask. (This code lives in trans2.c) */
1052 mask_convert(mask);
1055 for (p=mask; *p; p++)
1057 if (*p != '?' && *p != '*' && !isdoschar(*p))
1059 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1060 *p = '?';
1065 if (!strchr(mask,'.') && strlen(mask)>8)
1067 fstring tmp;
1068 fstrcpy(tmp,&mask[8]);
1069 mask[8] = '.';
1070 mask[9] = 0;
1071 pstrcat(mask,tmp);
1074 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1076 if (can_open)
1078 p = smb_buf(outbuf) + 3;
1080 ok = True;
1082 if (status_len == 0)
1084 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1085 if (dptr_num < 0)
1087 if(dptr_num == -2)
1089 if((errno == ENOENT) && bad_path)
1091 unix_ERR_class = ERRDOS;
1092 unix_ERR_code = ERRbadpath;
1094 return (UNIXERROR(ERRDOS,ERRnofids));
1096 return(ERROR(ERRDOS,ERRnofids));
1100 DEBUG(4,("dptr_num is %d\n",dptr_num));
1102 if (ok)
1104 if ((dirtype&0x1F) == aVOLID)
1106 memcpy(p,status,21);
1107 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1108 dptr_fill(p+12,dptr_num);
1109 if (dptr_zero(p+12) && (status_len==0))
1110 numentries = 1;
1111 else
1112 numentries = 0;
1113 p += DIR_STRUCT_SIZE;
1115 else
1117 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1118 conn->dirpath,lp_dontdescend(SNUM(conn))));
1119 if (in_list(conn->dirpath,
1120 lp_dontdescend(SNUM(conn)),True))
1121 check_descend = True;
1123 for (i=numentries;(i<maxentries) && !finished;i++)
1125 finished =
1126 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1127 if (!finished)
1129 memcpy(p,status,21);
1130 make_dir_struct(p,mask,fname,size,mode,date);
1131 dptr_fill(p+12,dptr_num);
1132 numentries++;
1134 p += DIR_STRUCT_SIZE;
1141 SearchEmpty:
1143 if (numentries == 0 || !ok)
1145 CVAL(outbuf,smb_rcls) = ERRDOS;
1146 SSVAL(outbuf,smb_err,ERRnofiles);
1149 /* If we were called as SMBffirst with smb_search_id == NULL
1150 and no entries were found then return error and close dirptr
1151 (X/Open spec) */
1153 if(ok && expect_close && numentries == 0 && status_len == 0)
1155 CVAL(outbuf,smb_rcls) = ERRDOS;
1156 SSVAL(outbuf,smb_err,ERRnofiles);
1157 /* Also close the dptr - we know it's gone */
1158 dptr_close(dptr_num);
1161 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1162 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1163 dptr_close(dptr_num);
1165 SSVAL(outbuf,smb_vwv0,numentries);
1166 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1167 CVAL(smb_buf(outbuf),0) = 5;
1168 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1170 if (Protocol >= PROTOCOL_NT1) {
1171 uint16 flg2 = SVAL(outbuf,smb_flg2);
1172 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1175 outsize += DIR_STRUCT_SIZE*numentries;
1176 smb_setlen(outbuf,outsize - 4);
1178 if ((! *directory) && dptr_path(dptr_num))
1179 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1181 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1182 smb_fn_name(CVAL(inbuf,smb_com)),
1183 mask, directory, dirtype, numentries, maxentries ) );
1185 return(outsize);
1189 /****************************************************************************
1190 reply to a fclose (stop directory search)
1191 ****************************************************************************/
1192 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1194 int outsize = 0;
1195 int status_len;
1196 char *path;
1197 char status[21];
1198 int dptr_num= -1;
1200 outsize = set_message(outbuf,1,0,True);
1201 path = smb_buf(inbuf) + 1;
1202 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1205 if (status_len == 0)
1206 return(ERROR(ERRSRV,ERRsrverror));
1208 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1210 if(dptr_fetch(status+12,&dptr_num)) {
1211 /* Close the dptr - we know it's gone */
1212 dptr_close(dptr_num);
1215 SSVAL(outbuf,smb_vwv0,0);
1217 DEBUG(3,("search close\n"));
1219 return(outsize);
1223 /****************************************************************************
1224 reply to an open
1225 ****************************************************************************/
1226 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1228 pstring fname;
1229 int outsize = 0;
1230 int fmode=0;
1231 int share_mode;
1232 int size = 0;
1233 time_t mtime=0;
1234 int unixmode;
1235 int rmode=0;
1236 struct stat sbuf;
1237 BOOL bad_path = False;
1238 files_struct *fsp;
1239 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1241 share_mode = SVAL(inbuf,smb_vwv0);
1243 pstrcpy(fname,smb_buf(inbuf)+1);
1244 unix_convert(fname,conn,0,&bad_path);
1246 fsp = file_new();
1247 if (!fsp)
1248 return(ERROR(ERRSRV,ERRnofids));
1250 if (!check_name(fname,conn))
1252 if((errno == ENOENT) && bad_path)
1254 unix_ERR_class = ERRDOS;
1255 unix_ERR_code = ERRbadpath;
1257 file_free(fsp);
1258 return(UNIXERROR(ERRDOS,ERRnoaccess));
1261 unixmode = unix_mode(conn,aARCH);
1263 open_file_shared(fsp,conn,fname,share_mode,3,unixmode,
1264 oplock_request,&rmode,NULL);
1266 if (!fsp->open)
1268 if((errno == ENOENT) && bad_path)
1270 unix_ERR_class = ERRDOS;
1271 unix_ERR_code = ERRbadpath;
1273 file_free(fsp);
1274 return(UNIXERROR(ERRDOS,ERRnoaccess));
1277 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1278 close_file(fsp,False);
1279 return(ERROR(ERRDOS,ERRnoaccess));
1282 size = sbuf.st_size;
1283 fmode = dos_mode(conn,fname,&sbuf);
1284 mtime = sbuf.st_mtime;
1286 if (fmode & aDIR) {
1287 DEBUG(3,("attempt to open a directory %s\n",fname));
1288 close_file(fsp,False);
1289 return(ERROR(ERRDOS,ERRnoaccess));
1292 outsize = set_message(outbuf,7,0,True);
1293 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1294 SSVAL(outbuf,smb_vwv1,fmode);
1295 if(lp_dos_filetime_resolution(SNUM(conn)) )
1296 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1297 else
1298 put_dos_date3(outbuf,smb_vwv2,mtime);
1299 SIVAL(outbuf,smb_vwv4,size);
1300 SSVAL(outbuf,smb_vwv6,rmode);
1302 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1303 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1306 if(fsp->granted_oplock)
1307 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1308 return(outsize);
1312 /****************************************************************************
1313 reply to an open and X
1314 ****************************************************************************/
1315 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1317 pstring fname;
1318 int smb_mode = SVAL(inbuf,smb_vwv3);
1319 int smb_attr = SVAL(inbuf,smb_vwv5);
1320 /* Breakout the oplock request bits so we can set the
1321 reply bits separately. */
1322 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1323 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1324 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1325 #if 0
1326 int open_flags = SVAL(inbuf,smb_vwv2);
1327 int smb_sattr = SVAL(inbuf,smb_vwv4);
1328 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1329 #endif
1330 int smb_ofun = SVAL(inbuf,smb_vwv8);
1331 int unixmode;
1332 int size=0,fmode=0,mtime=0,rmode=0;
1333 struct stat sbuf;
1334 int smb_action = 0;
1335 BOOL bad_path = False;
1336 files_struct *fsp;
1338 /* If it's an IPC, pass off the pipe handler. */
1339 if (IS_IPC(conn))
1340 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1342 /* XXXX we need to handle passed times, sattr and flags */
1344 pstrcpy(fname,smb_buf(inbuf));
1345 unix_convert(fname,conn,0,&bad_path);
1347 fsp = file_new();
1348 if (!fsp)
1349 return(ERROR(ERRSRV,ERRnofids));
1351 if (!check_name(fname,conn))
1353 if((errno == ENOENT) && bad_path)
1355 unix_ERR_class = ERRDOS;
1356 unix_ERR_code = ERRbadpath;
1358 file_free(fsp);
1359 return(UNIXERROR(ERRDOS,ERRnoaccess));
1362 unixmode = unix_mode(conn,smb_attr | aARCH);
1364 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1365 oplock_request, &rmode,&smb_action);
1367 if (!fsp->open)
1369 if((errno == ENOENT) && bad_path)
1371 unix_ERR_class = ERRDOS;
1372 unix_ERR_code = ERRbadpath;
1374 file_free(fsp);
1375 return(UNIXERROR(ERRDOS,ERRnoaccess));
1378 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1379 close_file(fsp,False);
1380 return(ERROR(ERRDOS,ERRnoaccess));
1383 size = sbuf.st_size;
1384 fmode = dos_mode(conn,fname,&sbuf);
1385 mtime = sbuf.st_mtime;
1386 if (fmode & aDIR) {
1387 close_file(fsp,False);
1388 return(ERROR(ERRDOS,ERRnoaccess));
1391 /* If the caller set the extended oplock request bit
1392 and we granted one (by whatever means) - set the
1393 correct bit for extended oplock reply.
1396 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1397 smb_action |= EXTENDED_OPLOCK_GRANTED;
1400 if(ex_oplock_request && fsp->granted_oplock) {
1401 smb_action |= EXTENDED_OPLOCK_GRANTED;
1404 /* If the caller set the core oplock request bit
1405 and we granted one (by whatever means) - set the
1406 correct bit for core oplock reply.
1409 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1410 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1413 if(core_oplock_request && fsp->granted_oplock) {
1414 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1417 set_message(outbuf,15,0,True);
1418 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1419 SSVAL(outbuf,smb_vwv3,fmode);
1420 if(lp_dos_filetime_resolution(SNUM(conn)) )
1421 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1422 else
1423 put_dos_date3(outbuf,smb_vwv4,mtime);
1424 SIVAL(outbuf,smb_vwv6,size);
1425 SSVAL(outbuf,smb_vwv8,rmode);
1426 SSVAL(outbuf,smb_vwv11,smb_action);
1428 chain_fsp = fsp;
1430 return chain_reply(inbuf,outbuf,length,bufsize);
1434 /****************************************************************************
1435 reply to a SMBulogoffX
1436 ****************************************************************************/
1437 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1439 uint16 vuid = SVAL(inbuf,smb_uid);
1440 user_struct *vuser = get_valid_user_struct(vuid);
1442 if(vuser == 0) {
1443 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1446 /* in user level security we are supposed to close any files
1447 open by this user */
1448 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1449 file_close_user(vuid);
1452 invalidate_vuid(vuid);
1454 set_message(outbuf,2,0,True);
1456 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1458 return chain_reply(inbuf,outbuf,length,bufsize);
1462 /****************************************************************************
1463 reply to a mknew or a create
1464 ****************************************************************************/
1465 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1467 pstring fname;
1468 int com;
1469 int outsize = 0;
1470 int createmode;
1471 mode_t unixmode;
1472 int ofun = 0;
1473 BOOL bad_path = False;
1474 files_struct *fsp;
1475 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1477 com = SVAL(inbuf,smb_com);
1479 createmode = SVAL(inbuf,smb_vwv0);
1480 pstrcpy(fname,smb_buf(inbuf)+1);
1481 unix_convert(fname,conn,0,&bad_path);
1483 if (createmode & aVOLID)
1485 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1488 unixmode = unix_mode(conn,createmode);
1490 fsp = file_new();
1491 if (!fsp)
1492 return(ERROR(ERRSRV,ERRnofids));
1494 if (!check_name(fname,conn))
1496 if((errno == ENOENT) && bad_path)
1498 unix_ERR_class = ERRDOS;
1499 unix_ERR_code = ERRbadpath;
1501 file_free(fsp);
1502 return(UNIXERROR(ERRDOS,ERRnoaccess));
1505 if(com == SMBmknew)
1507 /* We should fail if file exists. */
1508 ofun = 0x10;
1510 else
1512 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1513 ofun = 0x12;
1516 /* Open file in dos compatibility share mode. */
1517 open_file_shared(fsp,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1518 oplock_request, NULL, NULL);
1520 if (!fsp->open)
1522 if((errno == ENOENT) && bad_path)
1524 unix_ERR_class = ERRDOS;
1525 unix_ERR_code = ERRbadpath;
1527 file_free(fsp);
1528 return(UNIXERROR(ERRDOS,ERRnoaccess));
1531 outsize = set_message(outbuf,1,0,True);
1532 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1534 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1535 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1538 if(fsp->granted_oplock)
1539 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1541 DEBUG( 2, ( "new file %s\n", fname ) );
1542 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1543 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1545 return(outsize);
1549 /****************************************************************************
1550 reply to a create temporary file
1551 ****************************************************************************/
1552 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1554 pstring fname;
1555 pstring fname2;
1556 int outsize = 0;
1557 int createmode;
1558 mode_t unixmode;
1559 BOOL bad_path = False;
1560 files_struct *fsp;
1561 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1563 createmode = SVAL(inbuf,smb_vwv0);
1564 pstrcpy(fname,smb_buf(inbuf)+1);
1565 pstrcat(fname,"/TMXXXXXX");
1566 unix_convert(fname,conn,0,&bad_path);
1568 unixmode = unix_mode(conn,createmode);
1570 fsp = file_new();
1571 if (fsp)
1572 return(ERROR(ERRSRV,ERRnofids));
1574 if (!check_name(fname,conn))
1576 if((errno == ENOENT) && bad_path)
1578 unix_ERR_class = ERRDOS;
1579 unix_ERR_code = ERRbadpath;
1581 file_free(fsp);
1582 return(UNIXERROR(ERRDOS,ERRnoaccess));
1585 pstrcpy(fname2,(char *)mktemp(fname));
1587 /* Open file in dos compatibility share mode. */
1588 /* We should fail if file exists. */
1589 open_file_shared(fsp,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1590 oplock_request, NULL, NULL);
1592 if (!fsp->open)
1594 if((errno == ENOENT) && bad_path)
1596 unix_ERR_class = ERRDOS;
1597 unix_ERR_code = ERRbadpath;
1599 file_free(fsp);
1600 return(UNIXERROR(ERRDOS,ERRnoaccess));
1603 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1604 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1605 CVAL(smb_buf(outbuf),0) = 4;
1606 pstrcpy(smb_buf(outbuf) + 1,fname2);
1608 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1609 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1612 if(fsp->granted_oplock)
1613 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1615 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1616 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1617 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1619 return(outsize);
1623 /*******************************************************************
1624 check if a user is allowed to delete a file
1625 ********************************************************************/
1626 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1628 struct stat sbuf;
1629 int fmode;
1631 if (!CAN_WRITE(conn)) return(False);
1633 if (sys_lstat(fname,&sbuf) != 0) return(False);
1634 fmode = dos_mode(conn,fname,&sbuf);
1635 if (fmode & aDIR) return(False);
1636 if (!lp_delete_readonly(SNUM(conn))) {
1637 if (fmode & aRONLY) return(False);
1639 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1640 return(False);
1641 if (!check_file_sharing(conn,fname,False)) return(False);
1642 return(True);
1645 /****************************************************************************
1646 reply to a unlink
1647 ****************************************************************************/
1648 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1650 int outsize = 0;
1651 pstring name;
1652 int dirtype;
1653 pstring directory;
1654 pstring mask;
1655 char *p;
1656 int count=0;
1657 int error = ERRnoaccess;
1658 BOOL has_wild;
1659 BOOL exists=False;
1660 BOOL bad_path = False;
1662 *directory = *mask = 0;
1664 dirtype = SVAL(inbuf,smb_vwv0);
1666 pstrcpy(name,smb_buf(inbuf) + 1);
1668 DEBUG(3,("reply_unlink : %s\n",name));
1670 unix_convert(name,conn,0,&bad_path);
1672 p = strrchr(name,'/');
1673 if (!p) {
1674 pstrcpy(directory,"./");
1675 pstrcpy(mask,name);
1676 } else {
1677 *p = 0;
1678 pstrcpy(directory,name);
1679 pstrcpy(mask,p+1);
1682 if (is_mangled(mask))
1683 check_mangled_cache( mask );
1685 has_wild = strchr(mask,'*') || strchr(mask,'?');
1687 if (!has_wild) {
1688 pstrcat(directory,"/");
1689 pstrcat(directory,mask);
1690 if (can_delete(directory,conn,dirtype) && !sys_unlink(directory)) count++;
1691 if (!count) exists = file_exist(directory,NULL);
1692 } else {
1693 void *dirptr = NULL;
1694 char *dname;
1696 if (check_name(directory,conn))
1697 dirptr = OpenDir(conn, directory, True);
1699 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1700 the pattern matches against the long name, otherwise the short name
1701 We don't implement this yet XXXX
1704 if (dirptr)
1706 error = ERRbadfile;
1708 if (strequal(mask,"????????.???"))
1709 pstrcpy(mask,"*");
1711 while ((dname = ReadDirName(dirptr)))
1713 pstring fname;
1714 pstrcpy(fname,dname);
1716 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1718 error = ERRnoaccess;
1719 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1720 if (!can_delete(fname,conn,dirtype)) continue;
1721 if (!sys_unlink(fname)) count++;
1722 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1724 CloseDir(dirptr);
1728 if (count == 0) {
1729 if (exists)
1730 return(ERROR(ERRDOS,error));
1731 else
1733 if((errno == ENOENT) && bad_path)
1735 unix_ERR_class = ERRDOS;
1736 unix_ERR_code = ERRbadpath;
1738 return(UNIXERROR(ERRDOS,error));
1742 outsize = set_message(outbuf,0,0,True);
1744 return(outsize);
1748 /****************************************************************************
1749 reply to a readbraw (core+ protocol)
1750 ****************************************************************************/
1751 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1753 int maxcount,mincount;
1754 int nread = 0;
1755 uint32 startpos;
1756 char *header = outbuf;
1757 int ret=0;
1758 int fd;
1759 char *fname;
1760 files_struct *fsp;
1763 * Special check if an oplock break has been issued
1764 * and the readraw request croses on the wire, we must
1765 * return a zero length response here.
1768 if(global_oplock_break)
1770 _smb_setlen(header,0);
1771 transfer_file(0,Client,0,header,4,0);
1772 DEBUG(5,("readbraw - oplock break finished\n"));
1773 return -1;
1776 fsp = GETFSP(inbuf,smb_vwv0);
1778 startpos = IVAL(inbuf,smb_vwv1);
1779 maxcount = SVAL(inbuf,smb_vwv3);
1780 mincount = SVAL(inbuf,smb_vwv4);
1782 /* ensure we don't overrun the packet size */
1783 maxcount = MIN(65535,maxcount);
1784 maxcount = MAX(mincount,maxcount);
1786 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1787 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1788 _smb_setlen(header,0);
1789 transfer_file(0,Client,0,header,4,0);
1790 return(-1);
1791 } else {
1792 fd = fsp->fd_ptr->fd;
1793 fname = fsp->fsp_name;
1797 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1799 int size = fsp->size;
1800 int sizeneeded = startpos + maxcount;
1802 if (size < sizeneeded) {
1803 struct stat st;
1804 if (fstat(fsp->fd_ptr->fd,&st) == 0)
1805 size = st.st_size;
1806 if (!fsp->can_write)
1807 fsp->size = size;
1810 nread = MIN(maxcount,(int)(size - startpos));
1813 if (nread < mincount)
1814 nread = 0;
1816 DEBUG( 3, ( "readbraw fnum=%d start=%d max=%d min=%d nread=%d\n",
1817 fsp->fnum, startpos,
1818 maxcount, mincount, nread ) );
1820 #if UNSAFE_READRAW
1822 int predict=0;
1823 _smb_setlen(header,nread);
1825 #if USE_READ_PREDICTION
1826 if (!fsp->can_write)
1827 predict = read_predict(fd,startpos,header+4,NULL,nread);
1828 #endif
1830 if ((nread-predict) > 0)
1831 seek_file(fsp,startpos + predict);
1833 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1834 startpos+predict);
1837 if (ret != nread+4)
1838 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1839 fname,startpos,nread,ret));
1841 #else
1842 ret = read_file(fsp,header+4,startpos,nread);
1843 if (ret < mincount) ret = 0;
1845 _smb_setlen(header,ret);
1846 transfer_file(0,Client,0,header,4+ret,0);
1847 #endif
1849 DEBUG(5,("readbraw finished\n"));
1850 return -1;
1854 /****************************************************************************
1855 reply to a lockread (core+ protocol)
1856 ****************************************************************************/
1857 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsiz)
1859 int nread = -1;
1860 char *data;
1861 int outsize = 0;
1862 uint32 startpos, numtoread;
1863 int eclass;
1864 uint32 ecode;
1865 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
1867 CHECK_FSP(fsp,conn);
1868 CHECK_READ(fsp);
1869 CHECK_ERROR(fsp);
1871 numtoread = SVAL(inbuf,smb_vwv1);
1872 startpos = IVAL(inbuf,smb_vwv2);
1874 outsize = set_message(outbuf,5,3,True);
1875 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1876 data = smb_buf(outbuf) + 3;
1878 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode))
1879 return (ERROR(eclass,ecode));
1881 nread = read_file(fsp,data,startpos,numtoread);
1883 if (nread < 0)
1884 return(UNIXERROR(ERRDOS,ERRnoaccess));
1886 outsize += nread;
1887 SSVAL(outbuf,smb_vwv0,nread);
1888 SSVAL(outbuf,smb_vwv5,nread+3);
1889 SSVAL(smb_buf(outbuf),1,nread);
1891 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1892 fsp->fnum, numtoread, nread ) );
1894 return(outsize);
1898 /****************************************************************************
1899 reply to a read
1900 ****************************************************************************/
1901 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1903 int numtoread;
1904 int nread = 0;
1905 char *data;
1906 uint32 startpos;
1907 int outsize = 0;
1908 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
1910 CHECK_FSP(fsp,conn);
1911 CHECK_READ(fsp);
1912 CHECK_ERROR(fsp);
1914 numtoread = SVAL(inbuf,smb_vwv1);
1915 startpos = IVAL(inbuf,smb_vwv2);
1917 outsize = set_message(outbuf,5,3,True);
1918 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1919 data = smb_buf(outbuf) + 3;
1921 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
1922 return(ERROR(ERRDOS,ERRlock));
1924 if (numtoread > 0)
1925 nread = read_file(fsp,data,startpos,numtoread);
1927 if (nread < 0)
1928 return(UNIXERROR(ERRDOS,ERRnoaccess));
1930 outsize += nread;
1931 SSVAL(outbuf,smb_vwv0,nread);
1932 SSVAL(outbuf,smb_vwv5,nread+3);
1933 CVAL(smb_buf(outbuf),0) = 1;
1934 SSVAL(smb_buf(outbuf),1,nread);
1936 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1937 fsp->fnum, numtoread, nread ) );
1939 return(outsize);
1943 /****************************************************************************
1944 reply to a read and X
1945 ****************************************************************************/
1946 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1948 files_struct *fsp = GETFSP(inbuf,smb_vwv2);
1949 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1950 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1951 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1952 int nread = -1;
1953 char *data;
1954 BOOL ok = False;
1956 /* If it's an IPC, pass off the pipe handler. */
1957 if (IS_IPC(conn))
1958 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1960 CHECK_FSP(fsp,conn);
1961 CHECK_READ(fsp);
1962 CHECK_ERROR(fsp);
1964 set_message(outbuf,12,0,True);
1965 data = smb_buf(outbuf);
1967 if (is_locked(fsp,conn,smb_maxcnt,smb_offs, F_RDLCK))
1968 return(ERROR(ERRDOS,ERRlock));
1969 nread = read_file(fsp,data,smb_offs,smb_maxcnt);
1970 ok = True;
1972 if (nread < 0)
1973 return(UNIXERROR(ERRDOS,ERRnoaccess));
1975 SSVAL(outbuf,smb_vwv5,nread);
1976 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1977 SSVAL(smb_buf(outbuf),-2,nread);
1979 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
1980 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
1982 chain_fsp = fsp;
1984 return chain_reply(inbuf,outbuf,length,bufsize);
1988 /****************************************************************************
1989 reply to a writebraw (core+ or LANMAN1.0 protocol)
1990 ****************************************************************************/
1991 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1993 int nwritten=0;
1994 int total_written=0;
1995 int numtowrite=0;
1996 int outsize = 0;
1997 long startpos;
1998 char *data=NULL;
1999 BOOL write_through;
2000 int tcount;
2001 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2003 CHECK_FSP(fsp,conn);
2004 CHECK_WRITE(fsp);
2005 CHECK_ERROR(fsp);
2007 tcount = IVAL(inbuf,smb_vwv1);
2008 startpos = IVAL(inbuf,smb_vwv3);
2009 write_through = BITSETW(inbuf+smb_vwv7,0);
2011 /* We have to deal with slightly different formats depending
2012 on whether we are using the core+ or lanman1.0 protocol */
2013 if(Protocol <= PROTOCOL_COREPLUS) {
2014 numtowrite = SVAL(smb_buf(inbuf),-2);
2015 data = smb_buf(inbuf);
2016 } else {
2017 numtowrite = SVAL(inbuf,smb_vwv10);
2018 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2021 /* force the error type */
2022 CVAL(inbuf,smb_com) = SMBwritec;
2023 CVAL(outbuf,smb_com) = SMBwritec;
2025 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2026 return(ERROR(ERRDOS,ERRlock));
2028 if (seek_file(fsp,startpos) != startpos)
2029 DEBUG(0,("couldn't seek to %ld in writebraw\n",startpos));
2031 if (numtowrite>0)
2032 nwritten = write_file(fsp,data,numtowrite);
2034 DEBUG(3,("writebraw1 fnum=%d start=%ld num=%d wrote=%d sync=%d\n",
2035 fsp->fnum, startpos, numtowrite, nwritten, write_through));
2037 if (nwritten < numtowrite)
2038 return(UNIXERROR(ERRHRD,ERRdiskfull));
2040 total_written = nwritten;
2042 /* Return a message to the redirector to tell it
2043 to send more bytes */
2044 CVAL(outbuf,smb_com) = SMBwritebraw;
2045 SSVALS(outbuf,smb_vwv0,-1);
2046 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2047 send_smb(Client,outbuf);
2049 /* Now read the raw data into the buffer and write it */
2050 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2051 exit_server("secondary writebraw failed");
2054 /* Even though this is not an smb message, smb_len
2055 returns the generic length of an smb message */
2056 numtowrite = smb_len(inbuf);
2058 if (tcount > nwritten+numtowrite) {
2059 DEBUG(3,("Client overestimated the write %d %d %d\n",
2060 tcount,nwritten,numtowrite));
2063 nwritten = transfer_file(Client,fsp->fd_ptr->fd,numtowrite,NULL,0,
2064 startpos+nwritten);
2065 total_written += nwritten;
2067 /* Set up outbuf to return the correct return */
2068 outsize = set_message(outbuf,1,0,True);
2069 CVAL(outbuf,smb_com) = SMBwritec;
2070 SSVAL(outbuf,smb_vwv0,total_written);
2072 if (nwritten < numtowrite) {
2073 CVAL(outbuf,smb_rcls) = ERRHRD;
2074 SSVAL(outbuf,smb_err,ERRdiskfull);
2077 if (lp_syncalways(SNUM(conn)) || write_through)
2078 sync_file(conn,fsp);
2080 DEBUG(3,("writebraw2 fnum=%d start=%ld num=%d wrote=%d\n",
2081 fsp->fnum, startpos, numtowrite, total_written));
2083 /* we won't return a status if write through is not selected - this
2084 follows what WfWg does */
2085 if (!write_through && total_written==tcount)
2086 return(-1);
2088 return(outsize);
2092 /****************************************************************************
2093 reply to a writeunlock (core+)
2094 ****************************************************************************/
2095 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2097 int nwritten = -1;
2098 int outsize = 0;
2099 char *data;
2100 uint32 numtowrite,startpos;
2101 int eclass;
2102 uint32 ecode;
2103 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2105 CHECK_FSP(fsp,conn);
2106 CHECK_WRITE(fsp);
2107 CHECK_ERROR(fsp);
2109 numtowrite = SVAL(inbuf,smb_vwv1);
2110 startpos = IVAL(inbuf,smb_vwv2);
2111 data = smb_buf(inbuf) + 3;
2113 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2114 return(ERROR(ERRDOS,ERRlock));
2116 seek_file(fsp,startpos);
2118 /* The special X/Open SMB protocol handling of
2119 zero length writes is *NOT* done for
2120 this call */
2121 if(numtowrite == 0)
2122 nwritten = 0;
2123 else
2124 nwritten = write_file(fsp,data,numtowrite);
2126 if (lp_syncalways(SNUM(conn)))
2127 sync_file(conn,fsp);
2129 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2130 return(UNIXERROR(ERRDOS,ERRnoaccess));
2132 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2133 return(ERROR(eclass,ecode));
2135 outsize = set_message(outbuf,1,0,True);
2137 SSVAL(outbuf,smb_vwv0,nwritten);
2139 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2140 fsp->fnum, numtowrite, nwritten ) );
2142 return(outsize);
2146 /****************************************************************************
2147 reply to a write
2148 ****************************************************************************/
2149 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2151 int numtowrite;
2152 int nwritten = -1;
2153 int outsize = 0;
2154 int startpos;
2155 char *data;
2156 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2158 CHECK_FSP(fsp,conn);
2159 CHECK_WRITE(fsp);
2160 CHECK_ERROR(fsp);
2162 numtowrite = SVAL(inbuf,smb_vwv1);
2163 startpos = IVAL(inbuf,smb_vwv2);
2164 data = smb_buf(inbuf) + 3;
2166 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2167 return(ERROR(ERRDOS,ERRlock));
2169 seek_file(fsp,startpos);
2171 /* X/Open SMB protocol says that if smb_vwv1 is
2172 zero then the file size should be extended or
2173 truncated to the size given in smb_vwv[2-3] */
2174 if(numtowrite == 0)
2175 nwritten = set_filelen(fsp->fd_ptr->fd, startpos);
2176 else
2177 nwritten = write_file(fsp,data,numtowrite);
2179 if (lp_syncalways(SNUM(conn)))
2180 sync_file(conn,fsp);
2182 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2183 return(UNIXERROR(ERRDOS,ERRnoaccess));
2185 outsize = set_message(outbuf,1,0,True);
2187 SSVAL(outbuf,smb_vwv0,nwritten);
2189 if (nwritten < numtowrite) {
2190 CVAL(outbuf,smb_rcls) = ERRHRD;
2191 SSVAL(outbuf,smb_err,ERRdiskfull);
2194 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2195 fsp->fnum, numtowrite, nwritten));
2197 return(outsize);
2201 /****************************************************************************
2202 reply to a write and X
2203 ****************************************************************************/
2204 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2206 files_struct *fsp = GETFSP(inbuf,smb_vwv2);
2207 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2208 int smb_dsize = SVAL(inbuf,smb_vwv10);
2209 int smb_doff = SVAL(inbuf,smb_vwv11);
2210 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2211 int nwritten = -1;
2212 char *data;
2214 CHECK_FSP(fsp,conn);
2215 CHECK_WRITE(fsp);
2216 CHECK_ERROR(fsp);
2218 data = smb_base(inbuf) + smb_doff;
2220 if (is_locked(fsp,conn,smb_dsize,smb_offs, F_WRLCK))
2221 return(ERROR(ERRDOS,ERRlock));
2223 seek_file(fsp,smb_offs);
2225 /* X/Open SMB protocol says that, unlike SMBwrite
2226 if the length is zero then NO truncation is
2227 done, just a write of zero. To truncate a file,
2228 use SMBwrite. */
2229 if(smb_dsize == 0)
2230 nwritten = 0;
2231 else
2232 nwritten = write_file(fsp,data,smb_dsize);
2234 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2235 return(UNIXERROR(ERRDOS,ERRnoaccess));
2237 set_message(outbuf,6,0,True);
2239 SSVAL(outbuf,smb_vwv2,nwritten);
2241 if (nwritten < smb_dsize) {
2242 CVAL(outbuf,smb_rcls) = ERRHRD;
2243 SSVAL(outbuf,smb_err,ERRdiskfull);
2246 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2247 fsp->fnum, smb_dsize, nwritten));
2249 chain_fsp = fsp;
2251 if (lp_syncalways(SNUM(conn)) || write_through)
2252 sync_file(conn,fsp);
2254 return chain_reply(inbuf,outbuf,length,bufsize);
2258 /****************************************************************************
2259 reply to a lseek
2260 ****************************************************************************/
2261 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2263 uint32 startpos;
2264 int32 res= -1;
2265 int mode,umode;
2266 int outsize = 0;
2267 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2269 CHECK_FSP(fsp,conn);
2270 CHECK_ERROR(fsp);
2272 mode = SVAL(inbuf,smb_vwv1) & 3;
2273 startpos = IVAL(inbuf,smb_vwv2);
2275 switch (mode & 3)
2277 case 0: umode = SEEK_SET; break;
2278 case 1: umode = SEEK_CUR; break;
2279 case 2: umode = SEEK_END; break;
2280 default:
2281 umode = SEEK_SET; break;
2284 res = lseek(fsp->fd_ptr->fd,startpos,umode);
2285 fsp->pos = res;
2287 outsize = set_message(outbuf,2,0,True);
2288 SIVALS(outbuf,smb_vwv0,res);
2290 DEBUG(3,("lseek fnum=%d ofs=%d mode=%d\n",
2291 fsp->fnum, startpos, mode));
2293 return(outsize);
2297 /****************************************************************************
2298 reply to a flush
2299 ****************************************************************************/
2300 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2302 int outsize = set_message(outbuf,0,0,True);
2303 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2305 if (fsp) {
2306 CHECK_FSP(fsp,conn);
2307 CHECK_ERROR(fsp);
2310 if (!fsp) {
2311 file_sync_all(conn);
2312 } else {
2313 sync_file(conn,fsp);
2316 DEBUG(3,("flush\n"));
2317 return(outsize);
2321 /****************************************************************************
2322 reply to a exit
2323 ****************************************************************************/
2324 int reply_exit(connection_struct *conn,
2325 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2327 int outsize = set_message(outbuf,0,0,True);
2328 DEBUG(3,("exit\n"));
2330 return(outsize);
2334 /****************************************************************************
2335 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2336 ****************************************************************************/
2337 int reply_close(connection_struct *conn,
2338 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2340 int outsize = 0;
2341 time_t mtime;
2342 int32 eclass = 0, err = 0;
2343 files_struct *fsp = NULL;
2345 outsize = set_message(outbuf,0,0,True);
2347 /* If it's an IPC, pass off to the pipe handler. */
2348 if (IS_IPC(conn)) {
2349 return reply_pipe_close(conn, inbuf,outbuf);
2352 fsp = GETFSP(inbuf,smb_vwv0);
2355 * We can only use CHECK_FSP if we know it's not a directory.
2358 if(!(fsp && fsp->open && fsp->is_directory))
2359 CHECK_FSP(fsp,conn);
2361 if(HAS_CACHED_ERROR(fsp)) {
2362 eclass = fsp->wbmpx_ptr->wr_errclass;
2363 err = fsp->wbmpx_ptr->wr_error;
2366 if(fsp->is_directory) {
2368 * Special case - close NT SMB directory
2369 * handle.
2371 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2372 close_directory(fsp);
2373 } else {
2375 * Close ordinary file.
2377 mtime = make_unix_date3(inbuf+smb_vwv1);
2379 /* try and set the date */
2380 set_filetime(conn, fsp->fsp_name,mtime);
2382 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2383 fsp->fd_ptr->fd, fsp->fnum,
2384 conn->num_files_open));
2386 close_file(fsp,True);
2389 /* We have a cached error */
2390 if(eclass || err)
2391 return(ERROR(eclass,err));
2393 return(outsize);
2397 /****************************************************************************
2398 reply to a writeclose (Core+ protocol)
2399 ****************************************************************************/
2400 int reply_writeclose(connection_struct *conn,
2401 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2403 int numtowrite;
2404 int nwritten = -1;
2405 int outsize = 0;
2406 int startpos;
2407 char *data;
2408 time_t mtime;
2409 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2411 CHECK_FSP(fsp,conn);
2412 CHECK_WRITE(fsp);
2413 CHECK_ERROR(fsp);
2415 numtowrite = SVAL(inbuf,smb_vwv1);
2416 startpos = IVAL(inbuf,smb_vwv2);
2417 mtime = make_unix_date3(inbuf+smb_vwv4);
2418 data = smb_buf(inbuf) + 1;
2420 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2421 return(ERROR(ERRDOS,ERRlock));
2423 seek_file(fsp,startpos);
2425 nwritten = write_file(fsp,data,numtowrite);
2427 set_filetime(conn, fsp->fsp_name,mtime);
2429 close_file(fsp,True);
2431 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2432 fsp->fnum, numtowrite, nwritten,
2433 conn->num_files_open));
2435 if (nwritten <= 0)
2436 return(UNIXERROR(ERRDOS,ERRnoaccess));
2438 outsize = set_message(outbuf,1,0,True);
2440 SSVAL(outbuf,smb_vwv0,nwritten);
2441 return(outsize);
2445 /****************************************************************************
2446 reply to a lock
2447 ****************************************************************************/
2448 int reply_lock(connection_struct *conn,
2449 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2451 int outsize = set_message(outbuf,0,0,True);
2452 uint32 count,offset;
2453 int eclass;
2454 uint32 ecode;
2455 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2457 CHECK_FSP(fsp,conn);
2458 CHECK_ERROR(fsp);
2460 count = IVAL(inbuf,smb_vwv1);
2461 offset = IVAL(inbuf,smb_vwv3);
2463 DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n",
2464 fsp->fd_ptr->fd, fsp->fnum, offset, count));
2466 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode))
2467 return (ERROR(eclass,ecode));
2469 return(outsize);
2473 /****************************************************************************
2474 reply to a unlock
2475 ****************************************************************************/
2476 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2478 int outsize = set_message(outbuf,0,0,True);
2479 uint32 count,offset;
2480 int eclass;
2481 uint32 ecode;
2482 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2484 CHECK_FSP(fsp,conn);
2485 CHECK_ERROR(fsp);
2487 count = IVAL(inbuf,smb_vwv1);
2488 offset = IVAL(inbuf,smb_vwv3);
2490 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2491 return (ERROR(eclass,ecode));
2493 DEBUG( 3, ( "unlock fd=%d fnum=%d ofs=%d cnt=%d\n",
2494 fsp->fd_ptr->fd, fsp->fnum, offset, count ) );
2496 return(outsize);
2500 /****************************************************************************
2501 reply to a tdis
2502 ****************************************************************************/
2503 int reply_tdis(connection_struct *conn,
2504 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2506 int outsize = set_message(outbuf,0,0,True);
2507 uint16 vuid;
2509 vuid = SVAL(inbuf,smb_uid);
2511 if (!conn) {
2512 DEBUG(4,("Invalid connection in tdis\n"));
2513 return(ERROR(ERRSRV,ERRinvnid));
2516 conn->used = False;
2518 close_cnum(conn,vuid);
2520 return outsize;
2525 /****************************************************************************
2526 reply to a echo
2527 ****************************************************************************/
2528 int reply_echo(connection_struct *conn,
2529 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2531 int smb_reverb = SVAL(inbuf,smb_vwv0);
2532 int seq_num;
2533 int data_len = smb_buflen(inbuf);
2534 int outsize = set_message(outbuf,1,data_len,True);
2536 /* copy any incoming data back out */
2537 if (data_len > 0)
2538 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2540 if (smb_reverb > 100) {
2541 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2542 smb_reverb = 100;
2545 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2546 SSVAL(outbuf,smb_vwv0,seq_num);
2548 smb_setlen(outbuf,outsize - 4);
2550 send_smb(Client,outbuf);
2553 DEBUG(3,("echo %d times\n", smb_reverb));
2555 return -1;
2559 /****************************************************************************
2560 reply to a printopen
2561 ****************************************************************************/
2562 int reply_printopen(connection_struct *conn,
2563 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2565 pstring fname;
2566 pstring fname2;
2567 int outsize = 0;
2568 files_struct *fsp;
2570 *fname = *fname2 = 0;
2572 if (!CAN_PRINT(conn))
2573 return(ERROR(ERRDOS,ERRnoaccess));
2576 pstring s;
2577 char *p;
2578 pstrcpy(s,smb_buf(inbuf)+1);
2579 p = s;
2580 while (*p) {
2581 if (!(isalnum((int)*p) || strchr("._-",*p)))
2582 *p = 'X';
2583 p++;
2586 if (strlen(s) > 10) s[10] = 0;
2588 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2591 fsp = file_new();
2592 if (!fsp)
2593 return(ERROR(ERRSRV,ERRnofids));
2595 pstrcpy(fname2,(char *)mktemp(fname));
2597 if (!check_name(fname2,conn)) {
2598 file_free(fsp);
2599 return(ERROR(ERRDOS,ERRnoaccess));
2602 /* Open for exclusive use, write only. */
2603 open_file_shared(fsp,conn,fname2,
2604 (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0),
2605 0, NULL, NULL);
2607 if (!fsp->open) {
2608 file_free(fsp);
2609 return(UNIXERROR(ERRDOS,ERRnoaccess));
2612 /* force it to be a print file */
2613 fsp->print_file = True;
2615 outsize = set_message(outbuf,1,0,True);
2616 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2618 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2619 fname2, fsp->fd_ptr->fd, fsp->fnum));
2621 return(outsize);
2625 /****************************************************************************
2626 reply to a printclose
2627 ****************************************************************************/
2628 int reply_printclose(connection_struct *conn,
2629 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2631 int outsize = set_message(outbuf,0,0,True);
2632 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2634 CHECK_FSP(fsp,conn);
2635 CHECK_ERROR(fsp);
2637 if (!CAN_PRINT(conn))
2638 return(ERROR(ERRDOS,ERRnoaccess));
2640 DEBUG(3,("printclose fd=%d fnum=%d\n",
2641 fsp->fd_ptr->fd,fsp->fnum));
2643 close_file(fsp,True);
2645 return(outsize);
2649 /****************************************************************************
2650 reply to a printqueue
2651 ****************************************************************************/
2652 int reply_printqueue(connection_struct *conn,
2653 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2655 int outsize = set_message(outbuf,2,3,True);
2656 int max_count = SVAL(inbuf,smb_vwv0);
2657 int start_index = SVAL(inbuf,smb_vwv1);
2658 uint16 vuid;
2660 vuid = SVAL(inbuf,smb_uid);
2662 /* we used to allow the client to get the cnum wrong, but that
2663 is really quite gross and only worked when there was only
2664 one printer - I think we should now only accept it if they
2665 get it right (tridge) */
2666 if (!CAN_PRINT(conn))
2667 return(ERROR(ERRDOS,ERRnoaccess));
2669 SSVAL(outbuf,smb_vwv0,0);
2670 SSVAL(outbuf,smb_vwv1,0);
2671 CVAL(smb_buf(outbuf),0) = 1;
2672 SSVAL(smb_buf(outbuf),1,0);
2674 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2675 start_index, max_count));
2678 print_queue_struct *queue = NULL;
2679 char *p = smb_buf(outbuf) + 3;
2680 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2681 int num_to_get = ABS(max_count);
2682 int first = (max_count>0?start_index:start_index+max_count+1);
2683 int i;
2685 if (first >= count)
2686 num_to_get = 0;
2687 else
2688 num_to_get = MIN(num_to_get,count-first);
2691 for (i=first;i<first+num_to_get;i++) {
2692 put_dos_date2(p,0,queue[i].time);
2693 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2694 SSVAL(p,5,printjob_encode(SNUM(conn),
2695 queue[i].job));
2696 SIVAL(p,7,queue[i].size);
2697 CVAL(p,11) = 0;
2698 StrnCpy(p+12,queue[i].user,16);
2699 p += 28;
2702 if (count > 0) {
2703 outsize = set_message(outbuf,2,28*count+3,False);
2704 SSVAL(outbuf,smb_vwv0,count);
2705 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2706 CVAL(smb_buf(outbuf),0) = 1;
2707 SSVAL(smb_buf(outbuf),1,28*count);
2710 if (queue) free(queue);
2712 DEBUG(3,("%d entries returned in queue\n",count));
2715 return(outsize);
2719 /****************************************************************************
2720 reply to a printwrite
2721 ****************************************************************************/
2722 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2724 int numtowrite;
2725 int outsize = set_message(outbuf,0,0,True);
2726 char *data;
2727 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
2729 if (!CAN_PRINT(conn))
2730 return(ERROR(ERRDOS,ERRnoaccess));
2732 CHECK_FSP(fsp,conn);
2733 CHECK_WRITE(fsp);
2734 CHECK_ERROR(fsp);
2736 numtowrite = SVAL(smb_buf(inbuf),1);
2737 data = smb_buf(inbuf) + 3;
2739 if (write_file(fsp,data,numtowrite) != numtowrite)
2740 return(UNIXERROR(ERRDOS,ERRnoaccess));
2742 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2744 return(outsize);
2748 /****************************************************************************
2749 reply to a mkdir
2750 ****************************************************************************/
2751 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2753 pstring directory;
2754 int outsize,ret= -1;
2755 BOOL bad_path = False;
2757 pstrcpy(directory,smb_buf(inbuf) + 1);
2758 unix_convert(directory,conn,0,&bad_path);
2760 if (check_name(directory, conn))
2761 ret = sys_mkdir(directory,unix_mode(conn,aDIR));
2763 if (ret < 0)
2765 if((errno == ENOENT) && bad_path)
2767 unix_ERR_class = ERRDOS;
2768 unix_ERR_code = ERRbadpath;
2770 return(UNIXERROR(ERRDOS,ERRnoaccess));
2773 outsize = set_message(outbuf,0,0,True);
2775 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2777 return(outsize);
2780 /****************************************************************************
2781 Static function used by reply_rmdir to delete an entire directory
2782 tree recursively.
2783 ****************************************************************************/
2784 static BOOL recursive_rmdir(char *directory)
2786 char *dname = NULL;
2787 BOOL ret = False;
2788 void *dirptr = OpenDir(NULL, directory, False);
2790 if(dirptr == NULL)
2791 return True;
2793 while((dname = ReadDirName(dirptr)))
2795 pstring fullname;
2796 struct stat st;
2798 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2799 continue;
2801 /* Construct the full name. */
2802 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2804 errno = ENOMEM;
2805 ret = True;
2806 break;
2808 pstrcpy(fullname, directory);
2809 pstrcat(fullname, "/");
2810 pstrcat(fullname, dname);
2812 if(sys_lstat(fullname, &st) != 0)
2814 ret = True;
2815 break;
2818 if(st.st_mode & S_IFDIR)
2820 if(recursive_rmdir(fullname)!=0)
2822 ret = True;
2823 break;
2825 if(sys_rmdir(fullname) != 0)
2827 ret = True;
2828 break;
2831 else if(sys_unlink(fullname) != 0)
2833 ret = True;
2834 break;
2837 CloseDir(dirptr);
2838 return ret;
2841 /****************************************************************************
2842 reply to a rmdir
2843 ****************************************************************************/
2844 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2846 pstring directory;
2847 int outsize = 0;
2848 BOOL ok = False;
2849 BOOL bad_path = False;
2851 pstrcpy(directory,smb_buf(inbuf) + 1);
2852 unix_convert(directory,conn, NULL,&bad_path);
2854 if (check_name(directory,conn))
2857 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2858 ok = (sys_rmdir(directory) == 0);
2859 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2861 /* Check to see if the only thing in this directory are
2862 vetoed files/directories. If so then delete them and
2863 retry. If we fail to delete any of them (and we *don't*
2864 do a recursive delete) then fail the rmdir. */
2865 BOOL all_veto_files = True;
2866 char *dname;
2867 void *dirptr = OpenDir(conn, directory, False);
2869 if(dirptr != NULL)
2871 int dirpos = TellDir(dirptr);
2872 while ((dname = ReadDirName(dirptr)))
2874 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2875 continue;
2876 if(!IS_VETO_PATH(conn, dname))
2878 all_veto_files = False;
2879 break;
2882 if(all_veto_files)
2884 SeekDir(dirptr,dirpos);
2885 while ((dname = ReadDirName(dirptr)))
2887 pstring fullname;
2888 struct stat st;
2890 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2891 continue;
2893 /* Construct the full name. */
2894 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2896 errno = ENOMEM;
2897 break;
2899 pstrcpy(fullname, directory);
2900 pstrcat(fullname, "/");
2901 pstrcat(fullname, dname);
2903 if(sys_lstat(fullname, &st) != 0)
2904 break;
2905 if(st.st_mode & S_IFDIR)
2907 if(lp_recursive_veto_delete(SNUM(conn)))
2909 if(recursive_rmdir(fullname) != 0)
2910 break;
2912 if(sys_rmdir(fullname) != 0)
2913 break;
2915 else if(sys_unlink(fullname) != 0)
2916 break;
2918 CloseDir(dirptr);
2919 /* Retry the rmdir */
2920 ok = (sys_rmdir(directory) == 0);
2922 else
2923 CloseDir(dirptr);
2925 else
2926 errno = ENOTEMPTY;
2929 if (!ok)
2930 DEBUG(3,("couldn't remove directory %s : %s\n",
2931 directory,strerror(errno)));
2934 if (!ok)
2936 if((errno == ENOENT) && bad_path)
2938 unix_ERR_class = ERRDOS;
2939 unix_ERR_code = ERRbadpath;
2941 return(UNIXERROR(ERRDOS,ERRbadpath));
2944 outsize = set_message(outbuf,0,0,True);
2946 DEBUG( 3, ( "rmdir %s\n", directory ) );
2948 return(outsize);
2952 /*******************************************************************
2953 resolve wildcards in a filename rename
2954 ********************************************************************/
2955 static BOOL resolve_wildcards(char *name1,char *name2)
2957 fstring root1,root2;
2958 fstring ext1,ext2;
2959 char *p,*p2;
2961 name1 = strrchr(name1,'/');
2962 name2 = strrchr(name2,'/');
2964 if (!name1 || !name2) return(False);
2966 fstrcpy(root1,name1);
2967 fstrcpy(root2,name2);
2968 p = strrchr(root1,'.');
2969 if (p) {
2970 *p = 0;
2971 fstrcpy(ext1,p+1);
2972 } else {
2973 fstrcpy(ext1,"");
2975 p = strrchr(root2,'.');
2976 if (p) {
2977 *p = 0;
2978 fstrcpy(ext2,p+1);
2979 } else {
2980 fstrcpy(ext2,"");
2983 p = root1;
2984 p2 = root2;
2985 while (*p2) {
2986 if (*p2 == '?') {
2987 *p2 = *p;
2988 p2++;
2989 } else {
2990 p2++;
2992 if (*p) p++;
2995 p = ext1;
2996 p2 = ext2;
2997 while (*p2) {
2998 if (*p2 == '?') {
2999 *p2 = *p;
3000 p2++;
3001 } else {
3002 p2++;
3004 if (*p) p++;
3007 pstrcpy(name2,root2);
3008 if (ext2[0]) {
3009 pstrcat(name2,".");
3010 pstrcat(name2,ext2);
3013 return(True);
3016 /*******************************************************************
3017 check if a user is allowed to rename a file
3018 ********************************************************************/
3019 static BOOL can_rename(char *fname,connection_struct *conn)
3021 struct stat sbuf;
3023 if (!CAN_WRITE(conn)) return(False);
3025 if (sys_lstat(fname,&sbuf) != 0) return(False);
3026 if (!check_file_sharing(conn,fname,True)) return(False);
3028 return(True);
3031 /****************************************************************************
3032 The guts of the rename command, split out so it may be called by the NT SMB
3033 code.
3034 ****************************************************************************/
3035 int rename_internals(connection_struct *conn,
3036 char *inbuf, char *outbuf, char *name,
3037 char *newname, BOOL replace_if_exists)
3039 pstring directory;
3040 pstring mask;
3041 pstring newname_last_component;
3042 char *p;
3043 BOOL has_wild;
3044 BOOL bad_path1 = False;
3045 BOOL bad_path2 = False;
3046 int count=0;
3047 int error = ERRnoaccess;
3048 BOOL exists=False;
3050 *directory = *mask = 0;
3052 unix_convert(name,conn,0,&bad_path1);
3053 unix_convert(newname,conn,newname_last_component,&bad_path2);
3056 * Split the old name into directory and last component
3057 * strings. Note that unix_convert may have stripped off a
3058 * leading ./ from both name and newname if the rename is
3059 * at the root of the share. We need to make sure either both
3060 * name and newname contain a / character or neither of them do
3061 * as this is checked in resolve_wildcards().
3064 p = strrchr(name,'/');
3065 if (!p) {
3066 pstrcpy(directory,".");
3067 pstrcpy(mask,name);
3068 } else {
3069 *p = 0;
3070 pstrcpy(directory,name);
3071 pstrcpy(mask,p+1);
3072 *p = '/'; /* Replace needed for exceptional test below. */
3075 if (is_mangled(mask))
3076 check_mangled_cache( mask );
3078 has_wild = strchr(mask,'*') || strchr(mask,'?');
3080 if (!has_wild) {
3082 * No wildcards - just process the one file.
3084 BOOL is_short_name = is_8_3(name, True);
3086 /* Add a terminating '/' to the directory name. */
3087 pstrcat(directory,"/");
3088 pstrcat(directory,mask);
3090 /* Ensure newname contains a '/' also */
3091 if(strrchr(newname,'/') == 0) {
3092 pstring tmpstr;
3094 pstrcpy(tmpstr, "./");
3095 pstrcat(tmpstr, newname);
3096 pstrcpy(newname, tmpstr);
3099 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",
3100 case_sensitive, case_preserve, short_case_preserve, directory,
3101 newname, newname_last_component, is_short_name));
3104 * Check for special case with case preserving and not
3105 * case sensitive, if directory and newname are identical,
3106 * and the old last component differs from the original
3107 * last component only by case, then we should allow
3108 * the rename (user is trying to change the case of the
3109 * filename).
3111 if((case_sensitive == False) &&
3112 (((case_preserve == True) &&
3113 (is_short_name == False)) ||
3114 ((short_case_preserve == True) &&
3115 (is_short_name == True))) &&
3116 strcsequal(directory, newname)) {
3117 pstring newname_modified_last_component;
3120 * Get the last component of the modified name.
3121 * Note that we guarantee that newname contains a '/'
3122 * character above.
3124 p = strrchr(newname,'/');
3125 pstrcpy(newname_modified_last_component,p+1);
3127 if(strcsequal(newname_modified_last_component,
3128 newname_last_component) == False) {
3130 * Replace the modified last component with
3131 * the original.
3133 pstrcpy(p+1, newname_last_component);
3137 if(replace_if_exists) {
3139 * NT SMB specific flag - rename can overwrite
3140 * file with the same name so don't check for
3141 * file_exist().
3143 if(resolve_wildcards(directory,newname) &&
3144 can_rename(directory,conn) &&
3145 !sys_rename(directory,newname))
3146 count++;
3147 } else {
3148 if (resolve_wildcards(directory,newname) &&
3149 can_rename(directory,conn) &&
3150 !file_exist(newname,NULL) &&
3151 !sys_rename(directory,newname))
3152 count++;
3155 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3156 directory,newname));
3158 if (!count) exists = file_exist(directory,NULL);
3159 if (!count && exists && file_exist(newname,NULL)) {
3160 exists = True;
3161 error = 183;
3163 } else {
3165 * Wildcards - process each file that matches.
3167 void *dirptr = NULL;
3168 char *dname;
3169 pstring destname;
3171 if (check_name(directory,conn))
3172 dirptr = OpenDir(conn, directory, True);
3174 if (dirptr) {
3175 error = ERRbadfile;
3177 if (strequal(mask,"????????.???"))
3178 pstrcpy(mask,"*");
3180 while ((dname = ReadDirName(dirptr))) {
3181 pstring fname;
3182 pstrcpy(fname,dname);
3184 if(!mask_match(fname, mask, case_sensitive, False))
3185 continue;
3187 error = ERRnoaccess;
3188 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3189 if (!can_rename(fname,conn)) {
3190 DEBUG(6,("rename %s refused\n", fname));
3191 continue;
3193 pstrcpy(destname,newname);
3195 if (!resolve_wildcards(fname,destname)) {
3196 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3197 continue;
3200 if (!replace_if_exists && file_exist(destname,NULL)) {
3201 DEBUG(6,("file_exist %s\n", destname));
3202 error = 183;
3203 continue;
3206 if (!sys_rename(fname,destname))
3207 count++;
3208 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3210 CloseDir(dirptr);
3214 if (count == 0) {
3215 if (exists)
3216 return(ERROR(ERRDOS,error));
3217 else {
3218 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3219 unix_ERR_class = ERRDOS;
3220 unix_ERR_code = ERRbadpath;
3222 return(UNIXERROR(ERRDOS,error));
3226 return 0;
3229 /****************************************************************************
3230 Reply to a mv.
3231 ****************************************************************************/
3233 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3235 int outsize = 0;
3236 pstring name;
3237 pstring newname;
3239 pstrcpy(name,smb_buf(inbuf) + 1);
3240 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3242 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3244 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3245 if(outsize == 0)
3246 outsize = set_message(outbuf,0,0,True);
3248 return(outsize);
3251 /*******************************************************************
3252 copy a file as part of a reply_copy
3253 ******************************************************************/
3254 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3255 int count,BOOL target_is_directory)
3257 int Access,action;
3258 struct stat st;
3259 int ret=0;
3260 files_struct *fsp1,*fsp2;
3261 pstring dest;
3263 pstrcpy(dest,dest1);
3264 if (target_is_directory) {
3265 char *p = strrchr(src,'/');
3266 if (p)
3267 p++;
3268 else
3269 p = src;
3270 pstrcat(dest,"/");
3271 pstrcat(dest,p);
3274 if (!file_exist(src,&st)) return(False);
3276 fsp1 = file_new();
3277 if (!fsp1) return(False);
3278 open_file_shared(fsp1,conn,src,(DENY_NONE<<4),
3279 1,0,0,&Access,&action);
3281 if (!fsp1->open) {
3282 fsp1->reserved = False;
3283 return(False);
3286 if (!target_is_directory && count)
3287 ofun = 1;
3289 fsp2 = file_new();
3290 if (!fsp2) {
3291 close_file(fsp1,False);
3292 return(False);
3294 open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1,
3295 ofun,st.st_mode,0,&Access,&action);
3297 if (!fsp2->open) {
3298 close_file(fsp1,False);
3299 fsp2->reserved = False;
3300 return(False);
3303 if ((ofun&3) == 1) {
3304 lseek(fsp2->fd_ptr->fd,0,SEEK_END);
3307 if (st.st_size)
3308 ret = transfer_file(fsp1->fd_ptr->fd,
3309 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3311 close_file(fsp1,False);
3312 close_file(fsp2,False);
3314 return(ret == st.st_size);
3319 /****************************************************************************
3320 reply to a file copy.
3321 ****************************************************************************/
3322 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3324 int outsize = 0;
3325 pstring name;
3326 pstring directory;
3327 pstring mask,newname;
3328 char *p;
3329 int count=0;
3330 int error = ERRnoaccess;
3331 BOOL has_wild;
3332 BOOL exists=False;
3333 int tid2 = SVAL(inbuf,smb_vwv0);
3334 int ofun = SVAL(inbuf,smb_vwv1);
3335 int flags = SVAL(inbuf,smb_vwv2);
3336 BOOL target_is_directory=False;
3337 BOOL bad_path1 = False;
3338 BOOL bad_path2 = False;
3340 *directory = *mask = 0;
3342 pstrcpy(name,smb_buf(inbuf));
3343 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3345 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3347 if (tid2 != conn->cnum) {
3348 /* can't currently handle inter share copies XXXX */
3349 DEBUG(3,("Rejecting inter-share copy\n"));
3350 return(ERROR(ERRSRV,ERRinvdevice));
3353 unix_convert(name,conn,0,&bad_path1);
3354 unix_convert(newname,conn,0,&bad_path2);
3356 target_is_directory = directory_exist(newname,NULL);
3358 if ((flags&1) && target_is_directory) {
3359 return(ERROR(ERRDOS,ERRbadfile));
3362 if ((flags&2) && !target_is_directory) {
3363 return(ERROR(ERRDOS,ERRbadpath));
3366 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3367 /* wants a tree copy! XXXX */
3368 DEBUG(3,("Rejecting tree copy\n"));
3369 return(ERROR(ERRSRV,ERRerror));
3372 p = strrchr(name,'/');
3373 if (!p) {
3374 pstrcpy(directory,"./");
3375 pstrcpy(mask,name);
3376 } else {
3377 *p = 0;
3378 pstrcpy(directory,name);
3379 pstrcpy(mask,p+1);
3382 if (is_mangled(mask))
3383 check_mangled_cache( mask );
3385 has_wild = strchr(mask,'*') || strchr(mask,'?');
3387 if (!has_wild) {
3388 pstrcat(directory,"/");
3389 pstrcat(directory,mask);
3390 if (resolve_wildcards(directory,newname) &&
3391 copy_file(directory,newname,conn,ofun,
3392 count,target_is_directory)) count++;
3393 if (!count) exists = file_exist(directory,NULL);
3394 } else {
3395 void *dirptr = NULL;
3396 char *dname;
3397 pstring destname;
3399 if (check_name(directory,conn))
3400 dirptr = OpenDir(conn, directory, True);
3402 if (dirptr)
3404 error = ERRbadfile;
3406 if (strequal(mask,"????????.???"))
3407 pstrcpy(mask,"*");
3409 while ((dname = ReadDirName(dirptr)))
3411 pstring fname;
3412 pstrcpy(fname,dname);
3414 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3416 error = ERRnoaccess;
3417 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3418 pstrcpy(destname,newname);
3419 if (resolve_wildcards(fname,destname) &&
3420 copy_file(directory,newname,conn,ofun,
3421 count,target_is_directory)) count++;
3422 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3424 CloseDir(dirptr);
3428 if (count == 0) {
3429 if (exists)
3430 return(ERROR(ERRDOS,error));
3431 else
3433 if((errno == ENOENT) && (bad_path1 || bad_path2))
3435 unix_ERR_class = ERRDOS;
3436 unix_ERR_code = ERRbadpath;
3438 return(UNIXERROR(ERRDOS,error));
3442 outsize = set_message(outbuf,1,0,True);
3443 SSVAL(outbuf,smb_vwv0,count);
3445 return(outsize);
3450 /****************************************************************************
3451 reply to a setdir
3452 ****************************************************************************/
3453 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3455 int snum;
3456 int outsize = 0;
3457 BOOL ok = False;
3458 pstring newdir;
3460 snum = SNUM(conn);
3461 if (!CAN_SETDIR(snum))
3462 return(ERROR(ERRDOS,ERRnoaccess));
3464 pstrcpy(newdir,smb_buf(inbuf) + 1);
3465 strlower(newdir);
3467 if (strlen(newdir) == 0) {
3468 ok = True;
3469 } else {
3470 ok = directory_exist(newdir,NULL);
3471 if (ok) {
3472 string_set(&conn->connectpath,newdir);
3476 if (!ok)
3477 return(ERROR(ERRDOS,ERRbadpath));
3479 outsize = set_message(outbuf,0,0,True);
3480 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3482 DEBUG(3,("setdir %s\n", newdir));
3484 return(outsize);
3488 /****************************************************************************
3489 reply to a lockingX request
3490 ****************************************************************************/
3491 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3493 files_struct *fsp = GETFSP(inbuf,smb_vwv2);
3494 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3495 #if 0
3496 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3497 #endif
3498 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3499 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3500 uint32 count, offset;
3501 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3502 int i;
3503 char *data;
3504 uint32 ecode=0, dummy2;
3505 int eclass=0, dummy1;
3507 CHECK_FSP(fsp,conn);
3508 CHECK_ERROR(fsp);
3510 data = smb_buf(inbuf);
3512 /* Check if this is an oplock break on a file
3513 we have granted an oplock on.
3515 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3517 int token;
3518 uint32 dev = fsp->fd_ptr->dev;
3519 uint32 inode = fsp->fd_ptr->inode;
3521 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3522 fsp->fnum));
3524 * Make sure we have granted an oplock on this file.
3526 if(!fsp->granted_oplock)
3528 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3529 no oplock granted on this file.\n", fsp->fnum));
3530 return ERROR(ERRDOS,ERRlock);
3533 /* Remove the oplock flag from the sharemode. */
3534 lock_share_entry(fsp->conn, dev, inode, &token);
3535 if(remove_share_oplock(fsp, token)==False) {
3536 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3537 dev = %x, inode = %x\n",
3538 fsp->fnum, dev, inode));
3539 unlock_share_entry(fsp->conn, dev, inode, token);
3540 } else {
3541 unlock_share_entry(fsp->conn, dev, inode, token);
3543 /* Clear the granted flag and return. */
3544 fsp->granted_oplock = False;
3547 /* if this is a pure oplock break request then don't send a reply */
3548 if (num_locks == 0 && num_ulocks == 0)
3550 /* Sanity check - ensure a pure oplock break is not a
3551 chained request. */
3552 if(CVAL(inbuf,smb_vwv0) != 0xff)
3553 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3554 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3555 return -1;
3559 /* Data now points at the beginning of the list
3560 of smb_unlkrng structs */
3561 for(i = 0; i < (int)num_ulocks; i++) {
3562 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3563 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3564 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3565 return ERROR(eclass,ecode);
3568 /* Setup the timeout in seconds. */
3569 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3571 /* Now do any requested locks */
3572 data += 10*num_ulocks;
3573 /* Data now points at the beginning of the list
3574 of smb_lkrng structs */
3575 for(i = 0; i < (int)num_locks; i++) {
3576 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3577 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3578 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3579 &eclass, &ecode))
3580 #if 0 /* JRATEST - blocking lock code. */
3581 if((ecode == ERRlock) && (lock_timeout != 0)) {
3583 * A blocking lock was requested. Package up
3584 * this smb into a queued request and push it
3585 * onto the blocking lock queue.
3587 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3588 return -1;
3589 #endif /* JRATEST */
3590 break;
3593 /* If any of the above locks failed, then we must unlock
3594 all of the previous locks (X/Open spec). */
3595 if(i != num_locks && num_locks != 0) {
3596 for(; i >= 0; i--) {
3597 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3598 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3599 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3601 return ERROR(eclass,ecode);
3604 set_message(outbuf,2,0,True);
3606 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3607 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3609 chain_fsp = fsp;
3611 return chain_reply(inbuf,outbuf,length,bufsize);
3615 /****************************************************************************
3616 reply to a SMBreadbmpx (read block multiplex) request
3617 ****************************************************************************/
3618 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3620 int nread = -1;
3621 int total_read;
3622 char *data;
3623 uint32 startpos;
3624 int outsize, mincount, maxcount;
3625 int max_per_packet;
3626 int tcount;
3627 int pad;
3628 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
3630 /* this function doesn't seem to work - disable by default */
3631 if (!lp_readbmpx())
3632 return(ERROR(ERRSRV,ERRuseSTD));
3634 outsize = set_message(outbuf,8,0,True);
3636 CHECK_FSP(fsp,conn);
3637 CHECK_READ(fsp);
3638 CHECK_ERROR(fsp);
3640 startpos = IVAL(inbuf,smb_vwv1);
3641 maxcount = SVAL(inbuf,smb_vwv3);
3642 mincount = SVAL(inbuf,smb_vwv4);
3644 data = smb_buf(outbuf);
3645 pad = ((long)data)%4;
3646 if (pad) pad = 4 - pad;
3647 data += pad;
3649 max_per_packet = bufsize-(outsize+pad);
3650 tcount = maxcount;
3651 total_read = 0;
3653 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3654 return(ERROR(ERRDOS,ERRlock));
3658 int N = MIN(max_per_packet,tcount-total_read);
3660 nread = read_file(fsp,data,startpos,N);
3662 if (nread <= 0) nread = 0;
3664 if (nread < N)
3665 tcount = total_read + nread;
3667 set_message(outbuf,8,nread,False);
3668 SIVAL(outbuf,smb_vwv0,startpos);
3669 SSVAL(outbuf,smb_vwv2,tcount);
3670 SSVAL(outbuf,smb_vwv6,nread);
3671 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3673 send_smb(Client,outbuf);
3675 total_read += nread;
3676 startpos += nread;
3678 while (total_read < tcount);
3680 return(-1);
3684 /****************************************************************************
3685 reply to a SMBwritebmpx (write block multiplex primary) request
3686 ****************************************************************************/
3687 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3689 int numtowrite;
3690 int nwritten = -1;
3691 int outsize = 0;
3692 uint32 startpos;
3693 int tcount, write_through, smb_doff;
3694 char *data;
3695 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
3697 CHECK_FSP(fsp,conn);
3698 CHECK_WRITE(fsp);
3699 CHECK_ERROR(fsp);
3701 tcount = SVAL(inbuf,smb_vwv1);
3702 startpos = IVAL(inbuf,smb_vwv3);
3703 write_through = BITSETW(inbuf+smb_vwv7,0);
3704 numtowrite = SVAL(inbuf,smb_vwv10);
3705 smb_doff = SVAL(inbuf,smb_vwv11);
3707 data = smb_base(inbuf) + smb_doff;
3709 /* If this fails we need to send an SMBwriteC response,
3710 not an SMBwritebmpx - set this up now so we don't forget */
3711 CVAL(outbuf,smb_com) = SMBwritec;
3713 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3714 return(ERROR(ERRDOS,ERRlock));
3716 seek_file(fsp,startpos);
3717 nwritten = write_file(fsp,data,numtowrite);
3719 if(lp_syncalways(SNUM(conn)) || write_through)
3720 sync_file(conn,fsp);
3722 if(nwritten < numtowrite)
3723 return(UNIXERROR(ERRHRD,ERRdiskfull));
3725 /* If the maximum to be written to this file
3726 is greater than what we just wrote then set
3727 up a secondary struct to be attached to this
3728 fd, we will use this to cache error messages etc. */
3729 if(tcount > nwritten)
3731 write_bmpx_struct *wbms;
3732 if(fsp->wbmpx_ptr != NULL)
3733 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3734 else
3735 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3736 if(!wbms)
3738 DEBUG(0,("Out of memory in reply_readmpx\n"));
3739 return(ERROR(ERRSRV,ERRnoresource));
3741 wbms->wr_mode = write_through;
3742 wbms->wr_discard = False; /* No errors yet */
3743 wbms->wr_total_written = nwritten;
3744 wbms->wr_errclass = 0;
3745 wbms->wr_error = 0;
3746 fsp->wbmpx_ptr = wbms;
3749 /* We are returning successfully, set the message type back to
3750 SMBwritebmpx */
3751 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3753 outsize = set_message(outbuf,1,0,True);
3755 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3757 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3758 fsp->fnum, numtowrite, nwritten ) );
3760 if (write_through && tcount==nwritten) {
3761 /* we need to send both a primary and a secondary response */
3762 smb_setlen(outbuf,outsize - 4);
3763 send_smb(Client,outbuf);
3765 /* now the secondary */
3766 outsize = set_message(outbuf,1,0,True);
3767 CVAL(outbuf,smb_com) = SMBwritec;
3768 SSVAL(outbuf,smb_vwv0,nwritten);
3771 return(outsize);
3775 /****************************************************************************
3776 reply to a SMBwritebs (write block multiplex secondary) request
3777 ****************************************************************************/
3778 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3780 int numtowrite;
3781 int nwritten = -1;
3782 int outsize = 0;
3783 int32 startpos;
3784 int tcount, write_through, smb_doff;
3785 char *data;
3786 write_bmpx_struct *wbms;
3787 BOOL send_response = False;
3788 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
3790 CHECK_FSP(fsp,conn);
3791 CHECK_WRITE(fsp);
3793 tcount = SVAL(inbuf,smb_vwv1);
3794 startpos = IVAL(inbuf,smb_vwv2);
3795 numtowrite = SVAL(inbuf,smb_vwv6);
3796 smb_doff = SVAL(inbuf,smb_vwv7);
3798 data = smb_base(inbuf) + smb_doff;
3800 /* We need to send an SMBwriteC response, not an SMBwritebs */
3801 CVAL(outbuf,smb_com) = SMBwritec;
3803 /* This fd should have an auxiliary struct attached,
3804 check that it does */
3805 wbms = fsp->wbmpx_ptr;
3806 if(!wbms) return(-1);
3808 /* If write through is set we can return errors, else we must
3809 cache them */
3810 write_through = wbms->wr_mode;
3812 /* Check for an earlier error */
3813 if(wbms->wr_discard)
3814 return -1; /* Just discard the packet */
3816 seek_file(fsp,startpos);
3817 nwritten = write_file(fsp,data,numtowrite);
3819 if(lp_syncalways(SNUM(conn)) || write_through)
3820 sync_file(conn,fsp);
3822 if (nwritten < numtowrite)
3824 if(write_through) {
3825 /* We are returning an error - we can delete the aux struct */
3826 if (wbms) free((char *)wbms);
3827 fsp->wbmpx_ptr = NULL;
3828 return(ERROR(ERRHRD,ERRdiskfull));
3830 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3833 /* Increment the total written, if this matches tcount
3834 we can discard the auxiliary struct (hurrah !) and return a writeC */
3835 wbms->wr_total_written += nwritten;
3836 if(wbms->wr_total_written >= tcount)
3838 if (write_through) {
3839 outsize = set_message(outbuf,1,0,True);
3840 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3841 send_response = True;
3844 free((char *)wbms);
3845 fsp->wbmpx_ptr = NULL;
3848 if(send_response)
3849 return(outsize);
3851 return(-1);
3855 /****************************************************************************
3856 reply to a SMBsetattrE
3857 ****************************************************************************/
3858 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3860 struct utimbuf unix_times;
3861 int outsize = 0;
3862 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
3864 outsize = set_message(outbuf,0,0,True);
3866 CHECK_FSP(fsp,conn);
3867 CHECK_ERROR(fsp);
3869 /* Convert the DOS times into unix times. Ignore create
3870 time as UNIX can't set this.
3872 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3873 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3876 * Patch from Ray Frush <frush@engr.colostate.edu>
3877 * Sometimes times are sent as zero - ignore them.
3880 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3882 /* Ignore request */
3883 if( DEBUGLVL( 3 ) )
3885 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
3886 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
3888 return(outsize);
3890 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3892 /* set modify time = to access time if modify time was 0 */
3893 unix_times.modtime = unix_times.actime;
3896 /* Set the date on this file */
3897 if(file_utime(conn, fsp->fsp_name, &unix_times))
3898 return(ERROR(ERRDOS,ERRnoaccess));
3900 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
3901 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
3903 return(outsize);
3907 /****************************************************************************
3908 reply to a SMBgetattrE
3909 ****************************************************************************/
3910 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3912 struct stat sbuf;
3913 int outsize = 0;
3914 int mode;
3915 files_struct *fsp = GETFSP(inbuf,smb_vwv0);
3917 outsize = set_message(outbuf,11,0,True);
3919 CHECK_FSP(fsp,conn);
3920 CHECK_ERROR(fsp);
3922 /* Do an fstat on this file */
3923 if(fstat(fsp->fd_ptr->fd, &sbuf))
3924 return(UNIXERROR(ERRDOS,ERRnoaccess));
3926 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
3928 /* Convert the times into dos times. Set create
3929 date to be last modify date as UNIX doesn't save
3930 this */
3931 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
3932 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3933 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3934 if (mode & aDIR)
3936 SIVAL(outbuf,smb_vwv6,0);
3937 SIVAL(outbuf,smb_vwv8,0);
3939 else
3941 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3942 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3944 SSVAL(outbuf,smb_vwv10, mode);
3946 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
3948 return(outsize);