2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Andrew Bartlett 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL;
35 extern char magic_char;
36 extern BOOL case_sensitive;
37 extern BOOL case_preserve;
38 extern BOOL short_case_preserve;
39 extern userdom_struct current_user_info;
40 extern pstring global_myname;
41 extern int global_oplock_break;
42 uint32 global_client_caps = 0;
43 unsigned int smb_echo_count = 0;
45 extern fstring remote_machine;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
51 static void overflow_attack(int len)
54 dbgtext( "ERROR: Invalid password length %d.\n", len );
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr() );
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
66 int reply_special(char *inbuf,char *outbuf)
69 int msg_type = CVAL(inbuf,0);
70 int msg_flags = CVAL(inbuf,1);
73 extern fstring local_machine;
79 memset(outbuf,'\0',smb_size);
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
101 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
103 fstrcpy(local_machine,name1);
104 len = strlen(local_machine);
106 name_type = local_machine[15];
107 local_machine[15] = 0;
109 trim_string(local_machine," "," ");
110 strlower(local_machine);
111 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
113 DEBUG(2,("netbios connect: local=%s remote=%s\n",
114 local_machine, remote_machine ));
116 if (name_type == 'R') {
117 /* We are being asked for a pathworks session ---
119 CVAL(outbuf, 0) = 0x83;
123 /* only add the client's machine name to the list
124 of possibly valid usernames if we are operating
125 in share mode security */
126 if (lp_security() == SEC_SHARE) {
127 add_session_user(remote_machine);
130 reload_services(True);
133 claim_connection(NULL,"",MAXSTATUS,True);
137 case 0x89: /* session keepalive request
138 (some old clients produce this?) */
139 CVAL(outbuf,0) = 0x85;
143 case 0x82: /* positive session response */
144 case 0x83: /* negative session response */
145 case 0x84: /* retarget session response */
146 DEBUG(0,("Unexpected session response\n"));
149 case 0x85: /* session keepalive */
154 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
155 msg_type, msg_flags));
161 /****************************************************************************
163 ****************************************************************************/
165 int reply_tcon(connection_struct *conn,
166 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
172 uint16 vuid = SVAL(inbuf,smb_uid);
177 START_PROFILE(SMBtcon);
179 *service = *password = *dev = 0;
181 p = smb_buf(inbuf)+1;
182 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
183 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
184 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
186 p = strrchr_m(service,'\\');
188 pstrcpy(service, p+1);
191 conn = make_connection(service,password,pwlen,dev,vuid,&ecode);
194 END_PROFILE(SMBtcon);
195 return ERROR_NT(ecode);
198 outsize = set_message(outbuf,2,0,True);
199 SSVAL(outbuf,smb_vwv0,max_recv);
200 SSVAL(outbuf,smb_vwv1,conn->cnum);
201 SSVAL(outbuf,smb_tid,conn->cnum);
203 DEBUG(3,("tcon service=%s cnum=%d\n",
204 service, conn->cnum));
206 END_PROFILE(SMBtcon);
210 /****************************************************************************
211 Reply to a tcon and X.
212 ****************************************************************************/
214 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
220 uint16 vuid = SVAL(inbuf,smb_uid);
221 int passlen = SVAL(inbuf,smb_vwv3);
224 START_PROFILE(SMBtconX);
226 *service = *password = *devicename = 0;
228 /* we might have to close an old one */
229 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
230 close_cnum(conn,vuid);
233 if (passlen > MAX_PASS_LEN) {
234 overflow_attack(passlen);
235 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
238 memcpy(password,smb_buf(inbuf),passlen);
240 p = smb_buf(inbuf) + passlen;
241 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
244 if (strequal(password," "))
246 passlen = strlen(password);
251 * the service name can be either: \\server\share
252 * or share directly like on the DELL PowerVault 705
255 q = strchr_m(path+2,'\\');
257 END_PROFILE(SMBtconX);
258 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
260 fstrcpy(service,q+1);
263 fstrcpy(service,path);
265 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
267 DEBUG(4,("Got device type %s\n",devicename));
269 conn = make_connection(service,password,passlen,devicename,vuid,&ecode);
272 END_PROFILE(SMBtconX);
273 return ERROR_NT(ecode);
276 if (Protocol < PROTOCOL_NT1) {
277 set_message(outbuf,2,0,True);
279 p += srvstr_push(outbuf, p, devicename, -1,
280 STR_TERMINATE|STR_ASCII);
281 set_message_end(outbuf,p);
283 /* NT sets the fstype of IPC$ to the null string */
284 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
286 set_message(outbuf,3,0,True);
289 p += srvstr_push(outbuf, p, devicename, -1,
290 STR_TERMINATE|STR_ASCII);
291 p += srvstr_push(outbuf, p, fsname, -1,
294 set_message_end(outbuf,p);
296 /* what does setting this bit do? It is set by NT4 and
297 may affect the ability to autorun mounted cdroms */
298 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
300 init_dfsroot(conn, inbuf, outbuf);
304 DEBUG(3,("tconX service=%s \n",
307 /* set the incoming and outgoing tid to the just created one */
308 SSVAL(inbuf,smb_tid,conn->cnum);
309 SSVAL(outbuf,smb_tid,conn->cnum);
311 END_PROFILE(SMBtconX);
312 return chain_reply(inbuf,outbuf,length,bufsize);
316 /****************************************************************************
317 reply to an unknown type
318 ****************************************************************************/
319 int reply_unknown(char *inbuf,char *outbuf)
322 type = CVAL(inbuf,smb_com);
324 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
325 smb_fn_name(type), type, type));
327 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
331 /****************************************************************************
333 ****************************************************************************/
334 int reply_ioctl(connection_struct *conn,
335 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
337 uint16 device = SVAL(inbuf,smb_vwv1);
338 uint16 function = SVAL(inbuf,smb_vwv2);
339 uint32 ioctl_code = (device << 16) + function;
340 int replysize, outsize;
342 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
343 START_PROFILE(SMBioctl);
345 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
349 case IOCTL_QUERY_JOB_INFO:
353 END_PROFILE(SMBioctl);
354 return(ERROR_DOS(ERRSRV,ERRnosupport));
357 outsize = set_message(outbuf,8,replysize+1,True);
358 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
359 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
360 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
361 p = smb_buf(outbuf) + 1; /* Allow for alignment */
365 case IOCTL_QUERY_JOB_INFO:
366 SSVAL(p,0,fsp->print_jobid); /* Job number */
367 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
368 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
372 END_PROFILE(SMBioctl);
376 /****************************************************************************
377 This function breaks the authentication split. It needs sorting out.
378 I can't see why we can't hadle this INSIDE the check_password, as in then
379 end all it does it spit out an nt_status code.
380 ****************************************************************************/
381 /****************************************************************************
382 always return an error: it's just a matter of which one...
383 ****************************************************************************/
384 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
385 char *smb_passwd, int smb_passlen,
386 char *smb_nt_passwd, int smb_nt_passlen)
388 /* check if trust account exists */
389 SAM_ACCOUNT *sam_trust_acct = NULL;
392 auth_usersupplied_info user_info;
393 auth_serversupplied_info server_info;
394 AUTH_STR domain, smb_username, wksta_name;
396 ZERO_STRUCT(user_info);
397 ZERO_STRUCT(server_info);
399 ZERO_STRUCT(smb_username);
400 ZERO_STRUCT(wksta_name);
402 domain.str = lp_workgroup();
403 domain.len = strlen(domain.str);
405 user_info.requested_domain = domain;
406 user_info.domain = domain;
408 smb_username.str = user;
409 smb_username.len = strlen(smb_username.str);
411 user_info.unix_username = smb_username; /* For the time-being */
412 user_info.smb_username = smb_username;
414 user_info.wksta_name = wksta_name;
416 user_info.lm_resp.buffer = (uint8 *)smb_passwd;
417 user_info.lm_resp.len = smb_passlen;
418 user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd;
419 user_info.nt_resp.len = smb_nt_passlen;
421 if (!last_challenge(user_info.chal)) {
422 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
423 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
426 pdb_init_sam(&sam_trust_acct);
428 if (lp_security() == SEC_USER) {
429 ret = pdb_getsampwnam(sam_trust_acct, user);
431 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
432 pdb_free_sam(sam_trust_acct);
433 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
437 /* lkclXXXX: workstation entry doesn't exist */
438 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
439 pdb_free_sam(sam_trust_acct);
440 return(ERROR_NT(NT_STATUS_NO_SUCH_USER));
442 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
443 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
444 pdb_free_sam(sam_trust_acct);
445 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
448 if (!NT_STATUS_IS_OK(smb_password_ok(sam_trust_acct, &user_info, &server_info))) {
449 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
450 pdb_free_sam(sam_trust_acct);
451 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
454 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
455 pdb_free_sam(sam_trust_acct);
456 if (acct_ctrl & ACB_DOMTRUST) {
457 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
458 return(ERROR_NT(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
461 if (acct_ctrl & ACB_SVRTRUST) {
462 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
463 return(ERROR_NT(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
466 if (acct_ctrl & ACB_WSTRUST) {
467 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
468 return(ERROR_NT(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
472 /* don't know what to do: indicate logon failure */
473 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
477 /****************************************************************************
478 reply to a session setup command
479 ****************************************************************************/
481 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
488 int smb_apasslen = 0;
490 int smb_ntpasslen = 0;
491 pstring smb_ntpasswd;
496 fstring native_lanman;
498 static BOOL done_sesssetup = False;
499 BOOL doencrypt = lp_encrypted_passwords();
500 START_PROFILE(SMBsesssetupX);
502 ZERO_STRUCT(smb_apasswd);
503 ZERO_STRUCT(smb_ntpasswd);
505 smb_bufsize = SVAL(inbuf,smb_vwv2);
507 if (Protocol < PROTOCOL_NT1) {
508 smb_apasslen = SVAL(inbuf,smb_vwv7);
509 if (smb_apasslen > MAX_PASS_LEN) {
510 overflow_attack(smb_apasslen);
511 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
514 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
515 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
517 if (!doencrypt && (lp_security() != SEC_SERVER)) {
518 smb_apasslen = strlen(smb_apasswd);
521 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
522 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
523 enum remote_arch_types ra_type = get_remote_arch();
524 char *p = smb_buf(inbuf);
526 if(global_client_caps == 0)
527 global_client_caps = IVAL(inbuf,smb_vwv11);
529 /* client_caps is used as final determination if client is NT or Win95.
530 This is needed to return the correct error codes in some
534 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
535 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
536 set_remote_arch( RA_WIN95);
540 if (passlen1 != 24 && passlen2 < 24)
543 if (passlen1 > MAX_PASS_LEN) {
544 overflow_attack(passlen1);
545 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
548 passlen1 = MIN(passlen1, MAX_PASS_LEN);
549 passlen2 = MIN(passlen2, MAX_PASS_LEN);
552 /* both Win95 and WinNT stuff up the password lengths for
553 non-encrypting systems. Uggh.
555 if passlen1==24 its a win95 system, and its setting the
556 password length incorrectly. Luckily it still works with the
557 default code because Win95 will null terminate the password
560 if passlen1>0 and passlen2>0 then maybe its a NT box and its
561 setting passlen2 to some random value which really stuffs
562 things up. we need to fix that one. */
564 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
568 if (lp_restrict_anonymous()) {
569 /* there seems to be no reason behind the differences in MS clients formatting
570 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
571 * in particular seems to have an extra null byte between the username and the
572 * domain, or the password length calculation is wrong, which throws off the
573 * string extraction routines below. This makes the value of domain be the
574 * empty string, which fails the restrict anonymous check further down.
575 * This compensates for that, and allows browsing to work in mixed NT and
576 * win95 environments even when restrict anonymous is true. AAB
578 dump_data(100, p, 0x70);
579 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
580 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
581 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
582 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
583 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
588 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
589 /* Save the lanman2 password and the NT md4 password. */
590 smb_apasslen = passlen1;
591 memcpy(smb_apasswd,p,smb_apasslen);
592 smb_apasswd[smb_apasslen] = 0;
593 smb_ntpasslen = passlen2;
594 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
595 smb_ntpasswd[smb_ntpasslen] = 0;
597 /* we use the first password that they gave */
598 smb_apasslen = passlen1;
599 StrnCpy(smb_apasswd,p,smb_apasslen);
601 /* trim the password */
602 smb_apasslen = strlen(smb_apasswd);
604 /* wfwg sometimes uses a space instead of a null */
605 if (strequal(smb_apasswd," ")) {
611 p += passlen1 + passlen2;
612 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
615 * Incoming user and domain are in DOS codepage format. Convert
618 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
620 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
622 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
624 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
625 domain,native_os,native_lanman));
628 /* don't allow for weird usernames or domains */
629 alpha_strcpy(user, user, ". _-$", sizeof(user));
630 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
631 if (strstr(user, "..") || strstr(domain,"..")) {
632 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
635 if (lp_security() == SEC_SHARE) {
636 /* in share level we should ignore any passwords */
643 DEBUG(3,("sesssetupX:name=[%s]@[%s]\n",user, remote_machine));
645 /* If name ends in $ then I think it's asking about whether a */
646 /* computer with that name (minus the $) has access. For now */
647 /* say yes to everything ending in $. */
649 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
650 END_PROFILE(SMBsesssetupX);
651 return session_trust_account(conn, inbuf, outbuf, user,
652 smb_apasswd, smb_apasslen,
653 smb_ntpasswd, smb_ntpasslen);
656 if (done_sesssetup && lp_restrict_anonymous()) {
657 /* tests show that even if browsing is done over already validated connections
658 * without a username and password the domain is still provided, which it
659 * wouldn't be if it was a purely anonymous connection. So, in order to
660 * restrict anonymous, we only deny connections that have no session
661 * information. If a domain has been provided, then it's not a purely
662 * anonymous connection. AAB
664 if (!*user && !*smb_apasswd && !*domain) {
665 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
666 END_PROFILE(SMBsesssetupX);
667 return ERROR_DOS(ERRDOS,ERRnoaccess);
671 /* If no username is sent use the guest account */
673 pstrcpy(user,lp_guestaccount(-1));
677 pstrcpy(current_user_info.smb_name,user);
679 reload_services(True);
682 * Save the username before mapping. We will use
683 * the original username sent to us for security=server
684 * and security=domain checking.
687 pstrcpy( orig_user, user);
690 * Always try the "DOMAIN\user" lookup first, as this is the most
691 * specific case. If this fails then try the simple "user" lookup.
692 * But don't do this for guests, as this is always a local user.
698 /* Work out who's who */
700 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
701 domain, lp_winbind_separator(), user);
703 if (sys_getpwnam(dom_user) != NULL) {
704 pstrcpy(user, dom_user);
705 DEBUG(3,("Using unix username %s\n", dom_user));
709 * Pass the user through the NT -> unix user mapping
713 (void)map_username(user);
716 * Do any UNIX username case mangling.
718 smb_getpwnam(user, True);
721 add_session_user(user);
725 nt_status = pass_check_smb(orig_user, user,
726 domain, remote_machine,
727 (unsigned char *)smb_apasswd,
729 (unsigned char *)smb_ntpasswd,
732 if NT_STATUS_IS_OK(nt_status) {
734 } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)
735 && lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) {
736 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
737 pstrcpy(user,lp_guestaccount(-1));
740 } else if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)
741 || NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER))
742 && (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
743 pstrcpy(user,lp_guestaccount(-1));
744 DEBUG(3,("Registered username %s for guest access\n",user));
748 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
752 if (!strequal(user,lp_guestaccount(-1)) &&
753 lp_servicenumber(user) < 0)
755 add_home_service(user,get_user_home_dir(user));
759 /* it's ok - setup a reply */
760 if (Protocol < PROTOCOL_NT1) {
761 set_message(outbuf,3,0,True);
764 set_message(outbuf,3,0,True);
766 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
767 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
768 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
769 set_message_end(outbuf,p);
770 /* perhaps grab OS version here?? */
773 /* Set the correct uid in the outgoing and incoming packets
774 We will use this on future requests to determine which
775 user we should become.
778 const struct passwd *pw = smb_getpwnam(user,False);
780 DEBUG(1,("Username %s is invalid on this system\n",user));
781 END_PROFILE(SMBsesssetupX);
782 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
786 full_name = pw->pw_gecos;
790 SSVAL(outbuf,smb_vwv2,1);
792 /* register the name and uid as being validated, so further connections
793 to a uid can get through without a password, on the same VC */
795 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name);
797 if (sess_vuid == -1) {
798 return ERROR_DOS(ERRDOS,ERRnoaccess);
802 SSVAL(outbuf,smb_uid,sess_vuid);
803 SSVAL(inbuf,smb_uid,sess_vuid);
806 max_send = MIN(max_send,smb_bufsize);
808 DEBUG(6,("Client requested max send size of %d\n", max_send));
810 done_sesssetup = True;
812 END_PROFILE(SMBsesssetupX);
813 return chain_reply(inbuf,outbuf,length,bufsize);
816 /****************************************************************************
818 ****************************************************************************/
819 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
825 BOOL bad_path = False;
826 SMB_STRUCT_STAT sbuf;
827 START_PROFILE(SMBchkpth);
829 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
831 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
833 unix_convert(name,conn,0,&bad_path,&sbuf);
835 mode = SVAL(inbuf,smb_vwv0);
837 if (check_name(name,conn)) {
838 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
839 ok = S_ISDIR(sbuf.st_mode);
843 /* We special case this - as when a Windows machine
844 is parsing a path is steps through the components
845 one at a time - if a component fails it expects
846 ERRbadpath, not ERRbadfile.
848 if(errno == ENOENT) {
849 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
852 return(UNIXERROR(ERRDOS,ERRbadpath));
855 outsize = set_message(outbuf,0,0,True);
857 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
859 END_PROFILE(SMBchkpth);
864 /****************************************************************************
866 ****************************************************************************/
867 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
871 SMB_STRUCT_STAT sbuf;
876 BOOL bad_path = False;
878 START_PROFILE(SMBgetatr);
880 p = smb_buf(inbuf) + 1;
881 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
883 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
885 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
886 under WfWg - weird! */
889 mode = aHIDDEN | aDIR;
890 if (!CAN_WRITE(conn)) mode |= aRONLY;
897 unix_convert(fname,conn,0,&bad_path,&sbuf);
898 if (check_name(fname,conn))
900 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
902 mode = dos_mode(conn,fname,&sbuf);
904 mtime = sbuf.st_mtime;
910 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
916 if((errno == ENOENT) && bad_path)
918 unix_ERR_class = ERRDOS;
919 unix_ERR_code = ERRbadpath;
922 END_PROFILE(SMBgetatr);
923 return(UNIXERROR(ERRDOS,ERRbadfile));
926 outsize = set_message(outbuf,10,0,True);
928 SSVAL(outbuf,smb_vwv0,mode);
929 if(lp_dos_filetime_resolution(SNUM(conn)) )
930 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
932 put_dos_date3(outbuf,smb_vwv1,mtime);
933 SIVAL(outbuf,smb_vwv3,(uint32)size);
935 if (Protocol >= PROTOCOL_NT1) {
936 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
939 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
941 END_PROFILE(SMBgetatr);
946 /****************************************************************************
948 ****************************************************************************/
949 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
956 SMB_STRUCT_STAT sbuf;
957 BOOL bad_path = False;
960 START_PROFILE(SMBsetatr);
962 p = smb_buf(inbuf) + 1;
963 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
964 unix_convert(fname,conn,0,&bad_path,&sbuf);
966 mode = SVAL(inbuf,smb_vwv0);
967 mtime = make_unix_date3(inbuf+smb_vwv1);
969 if (VALID_STAT_OF_DIR(sbuf))
971 if (check_name(fname,conn))
972 ok = (file_chmod(conn,fname,mode,NULL) == 0);
974 ok = set_filetime(conn,fname,mtime);
978 if((errno == ENOENT) && bad_path)
980 unix_ERR_class = ERRDOS;
981 unix_ERR_code = ERRbadpath;
984 END_PROFILE(SMBsetatr);
985 return(UNIXERROR(ERRDOS,ERRnoaccess));
988 outsize = set_message(outbuf,0,0,True);
990 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
992 END_PROFILE(SMBsetatr);
997 /****************************************************************************
999 ****************************************************************************/
1000 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1003 SMB_BIG_UINT dfree,dsize,bsize;
1004 START_PROFILE(SMBdskattr);
1006 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1008 outsize = set_message(outbuf,5,0,True);
1010 SSVAL(outbuf,smb_vwv0,dsize);
1011 SSVAL(outbuf,smb_vwv1,bsize/512);
1012 SSVAL(outbuf,smb_vwv2,512);
1013 SSVAL(outbuf,smb_vwv3,dfree);
1015 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1017 END_PROFILE(SMBdskattr);
1022 /****************************************************************************
1024 Can be called from SMBsearch, SMBffirst or SMBfunique.
1025 ****************************************************************************/
1026 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1037 BOOL finished = False;
1046 BOOL check_descend = False;
1047 BOOL expect_close = False;
1048 BOOL can_open = True;
1049 BOOL bad_path = False;
1050 START_PROFILE(SMBsearch);
1052 *mask = *directory = *fname = 0;
1054 /* If we were called as SMBffirst then we must expect close. */
1055 if(CVAL(inbuf,smb_com) == SMBffirst)
1056 expect_close = True;
1058 outsize = set_message(outbuf,1,3,True);
1059 maxentries = SVAL(inbuf,smb_vwv0);
1060 dirtype = SVAL(inbuf,smb_vwv1);
1061 p = smb_buf(inbuf) + 1;
1062 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1064 status_len = SVAL(p, 0);
1067 /* dirtype &= ~aDIR; */
1069 if (status_len == 0)
1071 SMB_STRUCT_STAT sbuf;
1074 pstrcpy(directory,path);
1076 unix_convert(directory,conn,0,&bad_path,&sbuf);
1079 if (!check_name(directory,conn))
1082 p = strrchr_m(dir2,'/');
1094 p = strrchr_m(directory,'/');
1100 if (strlen(directory) == 0)
1101 pstrcpy(directory,"./");
1102 memset((char *)status,'\0',21);
1103 CVAL(status,0) = dirtype;
1107 memcpy(status,p,21);
1108 dirtype = CVAL(status,0) & 0x1F;
1109 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1112 string_set(&conn->dirpath,dptr_path(dptr_num));
1113 fstrcpy(mask, dptr_wcard(dptr_num));
1118 p = smb_buf(outbuf) + 3;
1122 if (status_len == 0)
1124 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1129 if((errno == ENOENT) && bad_path)
1131 unix_ERR_class = ERRDOS;
1132 unix_ERR_code = ERRbadpath;
1134 END_PROFILE(SMBsearch);
1135 return (UNIXERROR(ERRDOS,ERRnofids));
1137 END_PROFILE(SMBsearch);
1138 return ERROR_DOS(ERRDOS,ERRnofids);
1140 dptr_set_wcard(dptr_num, strdup(mask));
1143 DEBUG(4,("dptr_num is %d\n",dptr_num));
1147 if ((dirtype&0x1F) == aVOLID)
1149 memcpy(p,status,21);
1150 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1151 dptr_fill(p+12,dptr_num);
1152 if (dptr_zero(p+12) && (status_len==0))
1156 p += DIR_STRUCT_SIZE;
1160 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1161 conn->dirpath,lp_dontdescend(SNUM(conn))));
1162 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1163 check_descend = True;
1165 for (i=numentries;(i<maxentries) && !finished;i++)
1168 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1171 memcpy(p,status,21);
1172 make_dir_struct(p,mask,fname,size,mode,date);
1173 dptr_fill(p+12,dptr_num);
1176 p += DIR_STRUCT_SIZE;
1185 if (numentries == 0 || !ok)
1187 CVAL(outbuf,smb_rcls) = ERRDOS;
1188 SSVAL(outbuf,smb_err,ERRnofiles);
1189 dptr_close(&dptr_num);
1192 /* If we were called as SMBffirst with smb_search_id == NULL
1193 and no entries were found then return error and close dirptr
1196 if(ok && expect_close && numentries == 0 && status_len == 0)
1198 CVAL(outbuf,smb_rcls) = ERRDOS;
1199 SSVAL(outbuf,smb_err,ERRnofiles);
1200 /* Also close the dptr - we know it's gone */
1201 dptr_close(&dptr_num);
1204 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1205 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1206 dptr_close(&dptr_num);
1208 SSVAL(outbuf,smb_vwv0,numentries);
1209 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1210 CVAL(smb_buf(outbuf),0) = 5;
1211 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1213 if (Protocol >= PROTOCOL_NT1) {
1214 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1217 outsize += DIR_STRUCT_SIZE*numentries;
1218 smb_setlen(outbuf,outsize - 4);
1220 if ((! *directory) && dptr_path(dptr_num))
1221 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1223 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1224 smb_fn_name(CVAL(inbuf,smb_com)),
1225 mask, directory, dirtype, numentries, maxentries ) );
1227 END_PROFILE(SMBsearch);
1232 /****************************************************************************
1233 reply to a fclose (stop directory search)
1234 ****************************************************************************/
1235 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1244 START_PROFILE(SMBfclose);
1246 outsize = set_message(outbuf,1,0,True);
1247 p = smb_buf(inbuf) + 1;
1248 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1250 status_len = SVAL(p,0);
1253 if (status_len == 0) {
1254 END_PROFILE(SMBfclose);
1255 return ERROR_DOS(ERRSRV,ERRsrverror);
1258 memcpy(status,p,21);
1260 if(dptr_fetch(status+12,&dptr_num)) {
1261 /* Close the dptr - we know it's gone */
1262 dptr_close(&dptr_num);
1265 SSVAL(outbuf,smb_vwv0,0);
1267 DEBUG(3,("search close\n"));
1269 END_PROFILE(SMBfclose);
1274 /****************************************************************************
1276 ****************************************************************************/
1278 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1288 SMB_STRUCT_STAT sbuf;
1289 BOOL bad_path = False;
1291 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1292 START_PROFILE(SMBopen);
1294 share_mode = SVAL(inbuf,smb_vwv0);
1296 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1298 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1300 unix_convert(fname,conn,0,&bad_path,&sbuf);
1302 unixmode = unix_mode(conn,aARCH,fname);
1304 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1305 unixmode, oplock_request,&rmode,NULL);
1309 if((errno == ENOENT) && bad_path)
1311 unix_ERR_class = ERRDOS;
1312 unix_ERR_code = ERRbadpath;
1314 END_PROFILE(SMBopen);
1315 return(UNIXERROR(ERRDOS,ERRnoaccess));
1318 size = sbuf.st_size;
1319 fmode = dos_mode(conn,fname,&sbuf);
1320 mtime = sbuf.st_mtime;
1323 DEBUG(3,("attempt to open a directory %s\n",fname));
1324 close_file(fsp,False);
1325 END_PROFILE(SMBopen);
1326 return ERROR_DOS(ERRDOS,ERRnoaccess);
1329 outsize = set_message(outbuf,7,0,True);
1330 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1331 SSVAL(outbuf,smb_vwv1,fmode);
1332 if(lp_dos_filetime_resolution(SNUM(conn)) )
1333 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1335 put_dos_date3(outbuf,smb_vwv2,mtime);
1336 SIVAL(outbuf,smb_vwv4,(uint32)size);
1337 SSVAL(outbuf,smb_vwv6,rmode);
1339 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1340 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1343 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1344 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1345 END_PROFILE(SMBopen);
1350 /****************************************************************************
1351 reply to an open and X
1352 ****************************************************************************/
1353 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1356 int smb_mode = SVAL(inbuf,smb_vwv3);
1357 int smb_attr = SVAL(inbuf,smb_vwv5);
1358 /* Breakout the oplock request bits so we can set the
1359 reply bits separately. */
1360 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1361 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1362 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1364 int open_flags = SVAL(inbuf,smb_vwv2);
1365 int smb_sattr = SVAL(inbuf,smb_vwv4);
1366 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1368 int smb_ofun = SVAL(inbuf,smb_vwv8);
1371 int fmode=0,mtime=0,rmode=0;
1372 SMB_STRUCT_STAT sbuf;
1374 BOOL bad_path = False;
1376 START_PROFILE(SMBopenX);
1378 /* If it's an IPC, pass off the pipe handler. */
1380 if (lp_nt_pipe_support()) {
1381 END_PROFILE(SMBopenX);
1382 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1384 END_PROFILE(SMBopenX);
1385 return ERROR_DOS(ERRSRV,ERRaccess);
1389 /* XXXX we need to handle passed times, sattr and flags */
1390 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1392 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1394 unix_convert(fname,conn,0,&bad_path,&sbuf);
1396 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1398 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1399 oplock_request, &rmode,&smb_action);
1403 if((errno == ENOENT) && bad_path)
1405 unix_ERR_class = ERRDOS;
1406 unix_ERR_code = ERRbadpath;
1408 END_PROFILE(SMBopenX);
1409 return(UNIXERROR(ERRDOS,ERRnoaccess));
1412 size = sbuf.st_size;
1413 fmode = dos_mode(conn,fname,&sbuf);
1414 mtime = sbuf.st_mtime;
1416 close_file(fsp,False);
1417 END_PROFILE(SMBopenX);
1418 return ERROR_DOS(ERRDOS,ERRnoaccess);
1421 /* If the caller set the extended oplock request bit
1422 and we granted one (by whatever means) - set the
1423 correct bit for extended oplock reply.
1426 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1427 smb_action |= EXTENDED_OPLOCK_GRANTED;
1430 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1431 smb_action |= EXTENDED_OPLOCK_GRANTED;
1434 /* If the caller set the core oplock request bit
1435 and we granted one (by whatever means) - set the
1436 correct bit for core oplock reply.
1439 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1440 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1443 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1444 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1447 set_message(outbuf,15,0,True);
1448 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1449 SSVAL(outbuf,smb_vwv3,fmode);
1450 if(lp_dos_filetime_resolution(SNUM(conn)) )
1451 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1453 put_dos_date3(outbuf,smb_vwv4,mtime);
1454 SIVAL(outbuf,smb_vwv6,(uint32)size);
1455 SSVAL(outbuf,smb_vwv8,rmode);
1456 SSVAL(outbuf,smb_vwv11,smb_action);
1458 END_PROFILE(SMBopenX);
1459 return chain_reply(inbuf,outbuf,length,bufsize);
1463 /****************************************************************************
1464 reply to a SMBulogoffX
1465 ****************************************************************************/
1466 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1468 uint16 vuid = SVAL(inbuf,smb_uid);
1469 user_struct *vuser = get_valid_user_struct(vuid);
1470 START_PROFILE(SMBulogoffX);
1473 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1476 /* in user level security we are supposed to close any files
1477 open by this user */
1478 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1479 file_close_user(vuid);
1482 invalidate_vuid(vuid);
1484 set_message(outbuf,2,0,True);
1486 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1488 END_PROFILE(SMBulogoffX);
1489 return chain_reply(inbuf,outbuf,length,bufsize);
1493 /****************************************************************************
1494 reply to a mknew or a create
1495 ****************************************************************************/
1496 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1504 BOOL bad_path = False;
1506 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1507 SMB_STRUCT_STAT sbuf;
1508 START_PROFILE(SMBcreate);
1510 com = SVAL(inbuf,smb_com);
1512 createmode = SVAL(inbuf,smb_vwv0);
1513 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1515 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1517 unix_convert(fname,conn,0,&bad_path,&sbuf);
1519 if (createmode & aVOLID) {
1520 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1523 unixmode = unix_mode(conn,createmode,fname);
1527 /* We should fail if file exists. */
1528 ofun = FILE_CREATE_IF_NOT_EXIST;
1532 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1533 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1536 /* Open file in dos compatibility share mode. */
1537 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1538 ofun, unixmode, oplock_request, NULL, NULL);
1542 if((errno == ENOENT) && bad_path)
1544 unix_ERR_class = ERRDOS;
1545 unix_ERR_code = ERRbadpath;
1547 END_PROFILE(SMBcreate);
1548 return(UNIXERROR(ERRDOS,ERRnoaccess));
1551 outsize = set_message(outbuf,1,0,True);
1552 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1554 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1555 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1558 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1559 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1561 DEBUG( 2, ( "new file %s\n", fname ) );
1562 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1563 fname, fsp->fd, createmode, (int)unixmode ) );
1565 END_PROFILE(SMBcreate);
1570 /****************************************************************************
1571 reply to a create temporary file
1572 ****************************************************************************/
1573 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1579 BOOL bad_path = False;
1581 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1583 SMB_STRUCT_STAT sbuf;
1586 START_PROFILE(SMBctemp);
1588 createmode = SVAL(inbuf,smb_vwv0);
1589 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1590 pstrcat(fname,"\\TMXXXXXX");
1592 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1594 unix_convert(fname,conn,0,&bad_path,&sbuf);
1596 unixmode = unix_mode(conn,createmode,fname);
1598 tmpfd = smb_mkstemp(fname);
1600 END_PROFILE(SMBctemp);
1601 return(UNIXERROR(ERRDOS,ERRnoaccess));
1604 vfs_stat(conn,fname,&sbuf);
1606 /* Open file in dos compatibility share mode. */
1607 /* We should fail if file does not exist. */
1608 fsp = open_file_shared(conn,fname,&sbuf,
1609 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1610 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1611 unixmode, oplock_request, NULL, NULL);
1613 /* close fd from smb_mkstemp() */
1618 if((errno == ENOENT) && bad_path)
1620 unix_ERR_class = ERRDOS;
1621 unix_ERR_code = ERRbadpath;
1623 END_PROFILE(SMBctemp);
1624 return(UNIXERROR(ERRDOS,ERRnoaccess));
1627 outsize = set_message(outbuf,1,0,True);
1628 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1630 /* the returned filename is relative to the directory */
1631 s = strrchr_m(fname, '/');
1638 p = smb_buf(outbuf);
1639 SSVALS(p, 0, -1); /* what is this? not in spec */
1640 SSVAL(p, 2, strlen(s));
1642 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1643 outsize = set_message_end(outbuf, p);
1645 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1646 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1649 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1650 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1652 DEBUG( 2, ( "created temp file %s\n", fname ) );
1653 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1654 fname, fsp->fd, createmode, (int)unixmode ) );
1656 END_PROFILE(SMBctemp);
1661 /*******************************************************************
1662 check if a user is allowed to delete a file
1663 ********************************************************************/
1664 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1666 SMB_STRUCT_STAT sbuf;
1669 if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED;
1671 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1673 fmode = dos_mode(conn,fname,&sbuf);
1674 if (fmode & aDIR) return NT_STATUS_FILE_IS_A_DIRECTORY;
1675 if (!lp_delete_readonly(SNUM(conn))) {
1676 if (fmode & aRONLY) return NT_STATUS_CANNOT_DELETE;
1678 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1679 return NT_STATUS_CANNOT_DELETE;
1681 if (!check_file_sharing(conn,fname,False)) return NT_STATUS_SHARING_VIOLATION;
1683 return NT_STATUS_OK;
1686 /****************************************************************************
1687 The guts of the unlink command, split out so it may be called by the NT SMB
1689 ****************************************************************************/
1691 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1697 NTSTATUS error = NT_STATUS_OK;
1700 BOOL bad_path = False;
1702 SMB_STRUCT_STAT sbuf;
1704 *directory = *mask = 0;
1706 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1708 p = strrchr_m(name,'/');
1710 pstrcpy(directory,"./");
1714 pstrcpy(directory,name);
1719 * We should only check the mangled cache
1720 * here if unix_convert failed. This means
1721 * that the path in 'mask' doesn't exist
1722 * on the file system and so we need to look
1723 * for a possible mangle. This patch from
1724 * Tine Smukavec <valentin.smukavec@hermes.si>.
1727 if (!rc && is_mangled(mask))
1728 check_mangled_cache( mask );
1730 has_wild = ms_has_wild(mask);
1733 pstrcat(directory,"/");
1734 pstrcat(directory,mask);
1735 error = can_delete(directory,conn,dirtype);
1736 if (!NT_STATUS_IS_OK(error)) return error;
1738 if (vfs_unlink(conn,directory) == 0) {
1742 exists = vfs_file_exist(conn,directory,&sbuf);
1744 void *dirptr = NULL;
1747 if (check_name(directory,conn))
1748 dirptr = OpenDir(conn, directory, True);
1750 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1751 the pattern matches against the long name, otherwise the short name
1752 We don't implement this yet XXXX
1756 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1758 if (strequal(mask,"????????.???"))
1761 while ((dname = ReadDirName(dirptr))) {
1763 pstrcpy(fname,dname);
1765 if(!mask_match(fname, mask, case_sensitive)) continue;
1767 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1768 error = can_delete(fname,conn,dirtype);
1769 if (!NT_STATUS_IS_OK(error)) continue;
1770 if (vfs_unlink(conn,fname) == 0) count++;
1771 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1777 if (count == 0 && NT_STATUS_IS_OK(error)) {
1778 error = map_nt_error_from_unix(errno);
1784 /****************************************************************************
1786 ****************************************************************************/
1788 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1795 START_PROFILE(SMBunlink);
1797 dirtype = SVAL(inbuf,smb_vwv0);
1799 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1801 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1803 DEBUG(3,("reply_unlink : %s\n",name));
1805 status = unlink_internals(conn, dirtype, name);
1806 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1809 * Win2k needs a changenotify request response before it will
1810 * update after a rename..
1812 process_pending_change_notify_queue((time_t)0);
1814 outsize = set_message(outbuf,0,0,True);
1816 END_PROFILE(SMBunlink);
1820 /****************************************************************************
1822 ****************************************************************************/
1824 void fail_readraw(void)
1827 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)\n",
1829 exit_server(errstr);
1832 /****************************************************************************
1833 Reply to a readbraw (core+ protocol).
1834 ****************************************************************************/
1836 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1838 size_t maxcount,mincount;
1841 char *header = outbuf;
1844 START_PROFILE(SMBreadbraw);
1847 * Special check if an oplock break has been issued
1848 * and the readraw request croses on the wire, we must
1849 * return a zero length response here.
1852 if(global_oplock_break) {
1853 _smb_setlen(header,0);
1854 if (write_data(smbd_server_fd(),header,4) != 4)
1856 DEBUG(5,("readbraw - oplock break finished\n"));
1857 END_PROFILE(SMBreadbraw);
1861 fsp = file_fsp(inbuf,smb_vwv0);
1863 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1865 * fsp could be NULL here so use the value from the packet. JRA.
1867 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1868 _smb_setlen(header,0);
1869 if (write_data(smbd_server_fd(),header,4) != 4)
1871 END_PROFILE(SMBreadbraw);
1875 CHECK_FSP(fsp,conn);
1877 flush_write_cache(fsp, READRAW_FLUSH);
1879 startpos = IVAL(inbuf,smb_vwv1);
1880 if(CVAL(inbuf,smb_wct) == 10) {
1882 * This is a large offset (64 bit) read.
1884 #ifdef LARGE_SMB_OFF_T
1886 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1888 #else /* !LARGE_SMB_OFF_T */
1891 * Ensure we haven't been sent a >32 bit offset.
1894 if(IVAL(inbuf,smb_vwv8) != 0) {
1895 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1896 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1897 _smb_setlen(header,0);
1898 if (write_data(smbd_server_fd(),header,4) != 4)
1900 END_PROFILE(SMBreadbraw);
1904 #endif /* LARGE_SMB_OFF_T */
1907 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1908 _smb_setlen(header,0);
1909 if (write_data(smbd_server_fd(),header,4) != 4)
1911 END_PROFILE(SMBreadbraw);
1915 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1916 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1918 /* ensure we don't overrun the packet size */
1919 maxcount = MIN(65535,maxcount);
1920 maxcount = MAX(mincount,maxcount);
1922 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1923 SMB_OFF_T size = fsp->size;
1924 SMB_OFF_T sizeneeded = startpos + maxcount;
1926 if (size < sizeneeded) {
1928 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1930 if (!fsp->can_write)
1934 if (startpos >= size)
1937 nread = MIN(maxcount,(size - startpos));
1940 if (nread < mincount)
1943 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1944 (int)maxcount, (int)mincount, (int)nread ) );
1947 ret = read_file(fsp,header+4,startpos,nread);
1952 _smb_setlen(header,ret);
1953 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
1956 DEBUG(5,("readbraw finished\n"));
1957 END_PROFILE(SMBreadbraw);
1961 /****************************************************************************
1962 reply to a lockread (core+ protocol)
1963 ****************************************************************************/
1964 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1972 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1973 START_PROFILE(SMBlockread);
1975 CHECK_FSP(fsp,conn);
1978 release_level_2_oplocks_on_change(fsp);
1980 numtoread = SVAL(inbuf,smb_vwv1);
1981 startpos = IVAL(inbuf,smb_vwv2);
1983 outsize = set_message(outbuf,5,3,True);
1984 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1985 data = smb_buf(outbuf) + 3;
1988 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1989 * protocol request that predates the read/write lock concept.
1990 * Thus instead of asking for a read lock here we need to ask
1991 * for a write lock. JRA.
1994 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid),
1995 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1997 if (NT_STATUS_V(status)) {
1998 if (lp_blocking_locks(SNUM(conn))) {
2000 * A blocking lock was requested. Package up
2001 * this smb into a queued request and push it
2002 * onto the blocking lock queue.
2004 if(push_blocking_lock_request(inbuf, length, -1, 0))
2005 END_PROFILE(SMBlockread);
2008 END_PROFILE(SMBlockread);
2009 return ERROR_NT(status);
2012 nread = read_file(fsp,data,startpos,numtoread);
2015 END_PROFILE(SMBlockread);
2016 return(UNIXERROR(ERRDOS,ERRnoaccess));
2020 SSVAL(outbuf,smb_vwv0,nread);
2021 SSVAL(outbuf,smb_vwv5,nread+3);
2022 SSVAL(smb_buf(outbuf),1,nread);
2024 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2025 fsp->fnum, (int)numtoread, (int)nread));
2027 END_PROFILE(SMBlockread);
2032 /****************************************************************************
2034 ****************************************************************************/
2036 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2043 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2044 START_PROFILE(SMBread);
2046 CHECK_FSP(fsp,conn);
2049 numtoread = SVAL(inbuf,smb_vwv1);
2050 startpos = IVAL(inbuf,smb_vwv2);
2053 outsize = set_message(outbuf,5,3,True);
2054 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2055 data = smb_buf(outbuf) + 3;
2057 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2058 END_PROFILE(SMBread);
2059 return ERROR_DOS(ERRDOS,ERRlock);
2063 nread = read_file(fsp,data,startpos,numtoread);
2066 END_PROFILE(SMBread);
2067 return(UNIXERROR(ERRDOS,ERRnoaccess));
2071 SSVAL(outbuf,smb_vwv0,nread);
2072 SSVAL(outbuf,smb_vwv5,nread+3);
2073 CVAL(smb_buf(outbuf),0) = 1;
2074 SSVAL(smb_buf(outbuf),1,nread);
2076 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2077 fsp->fnum, (int)numtoread, (int)nread ) );
2079 END_PROFILE(SMBread);
2084 /****************************************************************************
2085 reply to a read and X
2086 ****************************************************************************/
2087 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2089 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2090 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2091 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2092 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2095 START_PROFILE(SMBreadX);
2097 /* If it's an IPC, pass off the pipe handler. */
2099 END_PROFILE(SMBreadX);
2100 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2103 CHECK_FSP(fsp,conn);
2106 set_message(outbuf,12,0,True);
2107 data = smb_buf(outbuf);
2109 if(CVAL(inbuf,smb_wct) == 12) {
2110 #ifdef LARGE_SMB_OFF_T
2112 * This is a large offset (64 bit) read.
2114 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2116 #else /* !LARGE_SMB_OFF_T */
2119 * Ensure we haven't been sent a >32 bit offset.
2122 if(IVAL(inbuf,smb_vwv10) != 0) {
2123 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2124 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2125 END_PROFILE(SMBreadX);
2126 return ERROR_DOS(ERRDOS,ERRbadaccess);
2129 #endif /* LARGE_SMB_OFF_T */
2133 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2134 END_PROFILE(SMBreadX);
2135 return ERROR_DOS(ERRDOS,ERRlock);
2137 nread = read_file(fsp,data,startpos,smb_maxcnt);
2140 END_PROFILE(SMBreadX);
2141 return(UNIXERROR(ERRDOS,ERRnoaccess));
2144 SSVAL(outbuf,smb_vwv5,nread);
2145 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2146 SSVAL(smb_buf(outbuf),-2,nread);
2148 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2149 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2151 END_PROFILE(SMBreadX);
2152 return chain_reply(inbuf,outbuf,length,bufsize);
2155 /****************************************************************************
2156 reply to a writebraw (core+ or LANMAN1.0 protocol)
2157 ****************************************************************************/
2159 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2162 ssize_t total_written=0;
2163 size_t numtowrite=0;
2168 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2170 START_PROFILE(SMBwritebraw);
2172 CHECK_FSP(fsp,conn);
2175 tcount = IVAL(inbuf,smb_vwv1);
2176 startpos = IVAL(inbuf,smb_vwv3);
2177 write_through = BITSETW(inbuf+smb_vwv7,0);
2179 /* We have to deal with slightly different formats depending
2180 on whether we are using the core+ or lanman1.0 protocol */
2182 if(Protocol <= PROTOCOL_COREPLUS) {
2183 numtowrite = SVAL(smb_buf(inbuf),-2);
2184 data = smb_buf(inbuf);
2186 numtowrite = SVAL(inbuf,smb_vwv10);
2187 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2190 /* force the error type */
2191 CVAL(inbuf,smb_com) = SMBwritec;
2192 CVAL(outbuf,smb_com) = SMBwritec;
2194 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2195 END_PROFILE(SMBwritebraw);
2196 return(ERROR_DOS(ERRDOS,ERRlock));
2200 nwritten = write_file(fsp,data,startpos,numtowrite);
2202 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2203 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2205 if (nwritten < numtowrite) {
2206 END_PROFILE(SMBwritebraw);
2207 return(UNIXERROR(ERRHRD,ERRdiskfull));
2210 total_written = nwritten;
2212 /* Return a message to the redirector to tell it to send more bytes */
2213 CVAL(outbuf,smb_com) = SMBwritebraw;
2214 SSVALS(outbuf,smb_vwv0,-1);
2215 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2216 if (!send_smb(smbd_server_fd(),outbuf))
2217 exit_server("reply_writebraw: send_smb failed.\n");
2219 /* Now read the raw data into the buffer and write it */
2220 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2221 exit_server("secondary writebraw failed");
2224 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2225 numtowrite = smb_len(inbuf);
2227 /* Set up outbuf to return the correct return */
2228 outsize = set_message(outbuf,1,0,True);
2229 CVAL(outbuf,smb_com) = SMBwritec;
2230 SSVAL(outbuf,smb_vwv0,total_written);
2232 if (numtowrite != 0) {
2234 if (numtowrite > BUFFER_SIZE) {
2235 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2236 (unsigned int)numtowrite ));
2237 exit_server("secondary writebraw failed");
2240 if (tcount > nwritten+numtowrite) {
2241 DEBUG(3,("Client overestimated the write %d %d %d\n",
2242 (int)tcount,(int)nwritten,(int)numtowrite));
2245 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2246 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2248 exit_server("secondary writebraw failed");
2251 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2253 if (nwritten < (ssize_t)numtowrite) {
2254 CVAL(outbuf,smb_rcls) = ERRHRD;
2255 SSVAL(outbuf,smb_err,ERRdiskfull);
2259 total_written += nwritten;
2262 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2263 sync_file(conn,fsp);
2265 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2266 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2268 /* we won't return a status if write through is not selected - this follows what WfWg does */
2269 END_PROFILE(SMBwritebraw);
2270 if (!write_through && total_written==tcount) {
2272 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2273 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2275 if (!send_keepalive(smbd_server_fd()))
2276 exit_server("reply_writebraw: send of keepalive failed");
2283 /****************************************************************************
2284 reply to a writeunlock (core+)
2285 ****************************************************************************/
2287 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2288 int size, int dum_buffsize)
2290 ssize_t nwritten = -1;
2295 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2297 START_PROFILE(SMBwriteunlock);
2299 CHECK_FSP(fsp,conn);
2302 numtowrite = SVAL(inbuf,smb_vwv1);
2303 startpos = IVAL(inbuf,smb_vwv2);
2304 data = smb_buf(inbuf) + 3;
2306 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2307 WRITE_LOCK,False)) {
2308 END_PROFILE(SMBwriteunlock);
2309 return ERROR_DOS(ERRDOS,ERRlock);
2312 /* The special X/Open SMB protocol handling of
2313 zero length writes is *NOT* done for
2318 nwritten = write_file(fsp,data,startpos,numtowrite);
2320 if (lp_syncalways(SNUM(conn)))
2321 sync_file(conn,fsp);
2323 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2324 END_PROFILE(SMBwriteunlock);
2325 return(UNIXERROR(ERRDOS,ERRnoaccess));
2328 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2329 (SMB_BIG_UINT)startpos);
2330 if (NT_STATUS_V(status)) {
2331 END_PROFILE(SMBwriteunlock);
2332 return ERROR_NT(status);
2335 outsize = set_message(outbuf,1,0,True);
2337 SSVAL(outbuf,smb_vwv0,nwritten);
2339 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2340 fsp->fnum, (int)numtowrite, (int)nwritten));
2342 END_PROFILE(SMBwriteunlock);
2347 /****************************************************************************
2349 ****************************************************************************/
2351 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2354 ssize_t nwritten = -1;
2357 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2359 START_PROFILE(SMBwrite);
2361 /* If it's an IPC, pass off the pipe handler. */
2363 END_PROFILE(SMBwrite);
2364 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2367 CHECK_FSP(fsp,conn);
2370 numtowrite = SVAL(inbuf,smb_vwv1);
2371 startpos = IVAL(inbuf,smb_vwv2);
2372 data = smb_buf(inbuf) + 3;
2374 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2375 END_PROFILE(SMBwrite);
2376 return ERROR_DOS(ERRDOS,ERRlock);
2379 /* X/Open SMB protocol says that if smb_vwv1 is
2380 zero then the file size should be extended or
2381 truncated to the size given in smb_vwv[2-3] */
2382 if(numtowrite == 0) {
2383 /* This is actually an allocate call, not set EOF. JRA */
2384 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2386 END_PROFILE(SMBwrite);
2387 return ERROR_NT(NT_STATUS_DISK_FULL);
2390 nwritten = write_file(fsp,data,startpos,numtowrite);
2392 if (lp_syncalways(SNUM(conn)))
2393 sync_file(conn,fsp);
2395 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2396 END_PROFILE(SMBwrite);
2397 return(UNIXERROR(ERRDOS,ERRnoaccess));
2400 outsize = set_message(outbuf,1,0,True);
2402 SSVAL(outbuf,smb_vwv0,nwritten);
2404 if (nwritten < (ssize_t)numtowrite) {
2405 CVAL(outbuf,smb_rcls) = ERRHRD;
2406 SSVAL(outbuf,smb_err,ERRdiskfull);
2409 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2410 fsp->fnum, (int)numtowrite, (int)nwritten));
2412 END_PROFILE(SMBwrite);
2417 /****************************************************************************
2418 reply to a write and X
2419 ****************************************************************************/
2420 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2422 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2423 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2424 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2425 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2426 ssize_t nwritten = -1;
2427 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2428 unsigned int smblen = smb_len(inbuf);
2430 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2431 START_PROFILE(SMBwriteX);
2433 /* If it's an IPC, pass off the pipe handler. */
2435 END_PROFILE(SMBwriteX);
2436 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2439 CHECK_FSP(fsp,conn);
2442 /* Deal with possible LARGE_WRITEX */
2444 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2446 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2447 END_PROFILE(SMBwriteX);
2448 return ERROR_DOS(ERRDOS,ERRbadmem);
2451 data = smb_base(inbuf) + smb_doff;
2453 if(CVAL(inbuf,smb_wct) == 14) {
2454 #ifdef LARGE_SMB_OFF_T
2456 * This is a large offset (64 bit) write.
2458 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2460 #else /* !LARGE_SMB_OFF_T */
2463 * Ensure we haven't been sent a >32 bit offset.
2466 if(IVAL(inbuf,smb_vwv12) != 0) {
2467 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2468 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2469 END_PROFILE(SMBwriteX);
2470 return ERROR_DOS(ERRDOS,ERRbadaccess);
2473 #endif /* LARGE_SMB_OFF_T */
2476 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2477 END_PROFILE(SMBwriteX);
2478 return ERROR_DOS(ERRDOS,ERRlock);
2481 /* X/Open SMB protocol says that, unlike SMBwrite
2482 if the length is zero then NO truncation is
2483 done, just a write of zero. To truncate a file,
2488 nwritten = write_file(fsp,data,startpos,numtowrite);
2490 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2491 END_PROFILE(SMBwriteX);
2492 return(UNIXERROR(ERRDOS,ERRnoaccess));
2495 set_message(outbuf,6,0,True);
2497 SSVAL(outbuf,smb_vwv2,nwritten);
2499 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2501 if (nwritten < (ssize_t)numtowrite) {
2502 CVAL(outbuf,smb_rcls) = ERRHRD;
2503 SSVAL(outbuf,smb_err,ERRdiskfull);
2506 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2507 fsp->fnum, (int)numtowrite, (int)nwritten));
2509 if (lp_syncalways(SNUM(conn)) || write_through)
2510 sync_file(conn,fsp);
2512 END_PROFILE(SMBwriteX);
2513 return chain_reply(inbuf,outbuf,length,bufsize);
2517 /****************************************************************************
2519 ****************************************************************************/
2521 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2527 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2528 START_PROFILE(SMBlseek);
2530 CHECK_FSP(fsp,conn);
2532 flush_write_cache(fsp, SEEK_FLUSH);
2534 mode = SVAL(inbuf,smb_vwv1) & 3;
2535 startpos = IVALS(inbuf,smb_vwv2);
2538 case 0: umode = SEEK_SET; break;
2539 case 1: umode = SEEK_CUR; break;
2540 case 2: umode = SEEK_END; break;
2542 umode = SEEK_SET; break;
2545 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2547 * Check for the special case where a seek before the start
2548 * of the file sets the offset to zero. Added in the CIFS spec,
2552 if(errno == EINVAL) {
2553 SMB_OFF_T current_pos = startpos;
2555 if(umode == SEEK_CUR) {
2557 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2558 END_PROFILE(SMBlseek);
2559 return(UNIXERROR(ERRDOS,ERRnoaccess));
2562 current_pos += startpos;
2564 } else if (umode == SEEK_END) {
2566 SMB_STRUCT_STAT sbuf;
2568 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2569 END_PROFILE(SMBlseek);
2570 return(UNIXERROR(ERRDOS,ERRnoaccess));
2573 current_pos += sbuf.st_size;
2577 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2581 END_PROFILE(SMBlseek);
2582 return(UNIXERROR(ERRDOS,ERRnoaccess));
2588 outsize = set_message(outbuf,2,0,True);
2589 SIVAL(outbuf,smb_vwv0,res);
2591 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2592 fsp->fnum, (double)startpos, (double)res, mode));
2594 END_PROFILE(SMBlseek);
2598 /****************************************************************************
2600 ****************************************************************************/
2602 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2604 int outsize = set_message(outbuf,0,0,True);
2605 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2606 START_PROFILE(SMBflush);
2608 CHECK_FSP(fsp,conn);
2611 file_sync_all(conn);
2613 sync_file(conn,fsp);
2616 DEBUG(3,("flush\n"));
2617 END_PROFILE(SMBflush);
2622 /****************************************************************************
2624 ****************************************************************************/
2625 int reply_exit(connection_struct *conn,
2626 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2629 START_PROFILE(SMBexit);
2630 outsize = set_message(outbuf,0,0,True);
2632 DEBUG(3,("exit\n"));
2634 END_PROFILE(SMBexit);
2639 /****************************************************************************
2640 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2641 ****************************************************************************/
2642 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2647 int32 eclass = 0, err = 0;
2648 files_struct *fsp = NULL;
2649 START_PROFILE(SMBclose);
2651 outsize = set_message(outbuf,0,0,True);
2653 /* If it's an IPC, pass off to the pipe handler. */
2655 END_PROFILE(SMBclose);
2656 return reply_pipe_close(conn, inbuf,outbuf);
2659 fsp = file_fsp(inbuf,smb_vwv0);
2662 * We can only use CHECK_FSP if we know it's not a directory.
2665 if(!fsp || (fsp->conn != conn)) {
2666 END_PROFILE(SMBclose);
2667 return ERROR_DOS(ERRDOS,ERRbadfid);
2670 if(fsp->is_directory || fsp->stat_open) {
2672 * Special case - close NT SMB directory or stat file
2675 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2676 close_file(fsp,True);
2679 * Close ordinary file.
2684 * If there was a modify time outstanding,
2685 * try and set it here.
2687 if(fsp->pending_modtime)
2688 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2691 * Now take care of any time sent in the close.
2693 mtime = make_unix_date3(inbuf+smb_vwv1);
2695 /* try and set the date */
2696 set_filetime(conn, fsp->fsp_name,mtime);
2698 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2700 conn->num_files_open));
2703 * close_file() returns the unix errno if an error
2704 * was detected on close - normally this is due to
2705 * a disk full error. If not then it was probably an I/O error.
2708 if((close_err = close_file(fsp,True)) != 0) {
2710 END_PROFILE(SMBclose);
2711 return (UNIXERROR(ERRHRD,ERRgeneral));
2715 /* We have a cached error */
2717 END_PROFILE(SMBclose);
2718 return ERROR_DOS(eclass,err);
2721 END_PROFILE(SMBclose);
2726 /****************************************************************************
2727 reply to a writeclose (Core+ protocol)
2728 ****************************************************************************/
2730 int reply_writeclose(connection_struct *conn,
2731 char *inbuf,char *outbuf, int size, int dum_buffsize)
2734 ssize_t nwritten = -1;
2740 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2741 START_PROFILE(SMBwriteclose);
2743 CHECK_FSP(fsp,conn);
2746 numtowrite = SVAL(inbuf,smb_vwv1);
2747 startpos = IVAL(inbuf,smb_vwv2);
2748 mtime = make_unix_date3(inbuf+smb_vwv4);
2749 data = smb_buf(inbuf) + 1;
2751 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2752 END_PROFILE(SMBwriteclose);
2753 return ERROR_DOS(ERRDOS,ERRlock);
2756 nwritten = write_file(fsp,data,startpos,numtowrite);
2758 set_filetime(conn, fsp->fsp_name,mtime);
2760 close_err = close_file(fsp,True);
2762 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2763 fsp->fnum, (int)numtowrite, (int)nwritten,
2764 conn->num_files_open));
2766 if (nwritten <= 0) {
2767 END_PROFILE(SMBwriteclose);
2768 return(UNIXERROR(ERRDOS,ERRnoaccess));
2771 if(close_err != 0) {
2773 END_PROFILE(SMBwriteclose);
2774 return(UNIXERROR(ERRHRD,ERRgeneral));
2777 outsize = set_message(outbuf,1,0,True);
2779 SSVAL(outbuf,smb_vwv0,nwritten);
2780 END_PROFILE(SMBwriteclose);
2785 /****************************************************************************
2787 ****************************************************************************/
2788 int reply_lock(connection_struct *conn,
2789 char *inbuf,char *outbuf, int length, int dum_buffsize)
2791 int outsize = set_message(outbuf,0,0,True);
2792 SMB_BIG_UINT count,offset;
2794 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2795 START_PROFILE(SMBlock);
2797 CHECK_FSP(fsp,conn);
2799 release_level_2_oplocks_on_change(fsp);
2801 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2802 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2804 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2805 fsp->fd, fsp->fnum, (double)offset, (double)count));
2807 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2808 if (NT_STATUS_V(status)) {
2809 if (lp_blocking_locks(SNUM(conn))) {
2811 * A blocking lock was requested. Package up
2812 * this smb into a queued request and push it
2813 * onto the blocking lock queue.
2815 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2816 END_PROFILE(SMBlock);
2820 END_PROFILE(SMBlock);
2821 return ERROR_NT(status);
2824 END_PROFILE(SMBlock);
2829 /****************************************************************************
2831 ****************************************************************************/
2832 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2835 int outsize = set_message(outbuf,0,0,True);
2836 SMB_BIG_UINT count,offset;
2838 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2839 START_PROFILE(SMBunlock);
2841 CHECK_FSP(fsp,conn);
2843 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2844 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2846 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2847 if (NT_STATUS_V(status)) {
2848 END_PROFILE(SMBunlock);
2849 return ERROR_NT(status);
2852 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2853 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2855 END_PROFILE(SMBunlock);
2860 /****************************************************************************
2862 ****************************************************************************/
2863 int reply_tdis(connection_struct *conn,
2864 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2866 int outsize = set_message(outbuf,0,0,True);
2868 START_PROFILE(SMBtdis);
2870 vuid = SVAL(inbuf,smb_uid);
2873 DEBUG(4,("Invalid connection in tdis\n"));
2874 END_PROFILE(SMBtdis);
2875 return ERROR_DOS(ERRSRV,ERRinvnid);
2880 close_cnum(conn,vuid);
2882 END_PROFILE(SMBtdis);
2888 /****************************************************************************
2890 ****************************************************************************/
2891 int reply_echo(connection_struct *conn,
2892 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2894 int smb_reverb = SVAL(inbuf,smb_vwv0);
2896 unsigned int data_len = smb_buflen(inbuf);
2897 int outsize = set_message(outbuf,1,data_len,True);
2898 START_PROFILE(SMBecho);
2900 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2902 /* copy any incoming data back out */
2904 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2906 if (smb_reverb > 100) {
2907 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2911 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2912 SSVAL(outbuf,smb_vwv0,seq_num);
2914 smb_setlen(outbuf,outsize - 4);
2916 if (!send_smb(smbd_server_fd(),outbuf))
2917 exit_server("reply_echo: send_smb failed.\n");
2920 DEBUG(3,("echo %d times\n", smb_reverb));
2924 END_PROFILE(SMBecho);
2929 /****************************************************************************
2930 reply to a printopen
2931 ****************************************************************************/
2932 int reply_printopen(connection_struct *conn,
2933 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2937 START_PROFILE(SMBsplopen);
2939 if (!CAN_PRINT(conn)) {
2940 END_PROFILE(SMBsplopen);
2941 return ERROR_DOS(ERRDOS,ERRnoaccess);
2944 /* Open for exclusive use, write only. */
2945 fsp = print_fsp_open(conn);
2948 END_PROFILE(SMBsplopen);
2949 return(UNIXERROR(ERRDOS,ERRnoaccess));
2952 outsize = set_message(outbuf,1,0,True);
2953 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2955 DEBUG(3,("openprint fd=%d fnum=%d\n",
2956 fsp->fd, fsp->fnum));
2958 END_PROFILE(SMBsplopen);
2963 /****************************************************************************
2964 reply to a printclose
2965 ****************************************************************************/
2966 int reply_printclose(connection_struct *conn,
2967 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2969 int outsize = set_message(outbuf,0,0,True);
2970 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2972 START_PROFILE(SMBsplclose);
2974 CHECK_FSP(fsp,conn);
2976 if (!CAN_PRINT(conn)) {
2977 END_PROFILE(SMBsplclose);
2978 return ERROR_DOS(ERRDOS,ERRnoaccess);
2981 DEBUG(3,("printclose fd=%d fnum=%d\n",
2982 fsp->fd,fsp->fnum));
2984 close_err = close_file(fsp,True);
2986 if(close_err != 0) {
2988 END_PROFILE(SMBsplclose);
2989 return(UNIXERROR(ERRHRD,ERRgeneral));
2992 END_PROFILE(SMBsplclose);
2997 /****************************************************************************
2998 reply to a printqueue
2999 ****************************************************************************/
3000 int reply_printqueue(connection_struct *conn,
3001 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3003 int outsize = set_message(outbuf,2,3,True);
3004 int max_count = SVAL(inbuf,smb_vwv0);
3005 int start_index = SVAL(inbuf,smb_vwv1);
3006 START_PROFILE(SMBsplretq);
3008 /* we used to allow the client to get the cnum wrong, but that
3009 is really quite gross and only worked when there was only
3010 one printer - I think we should now only accept it if they
3011 get it right (tridge) */
3012 if (!CAN_PRINT(conn)) {
3013 END_PROFILE(SMBsplretq);
3014 return ERROR_DOS(ERRDOS,ERRnoaccess);
3017 SSVAL(outbuf,smb_vwv0,0);
3018 SSVAL(outbuf,smb_vwv1,0);
3019 CVAL(smb_buf(outbuf),0) = 1;
3020 SSVAL(smb_buf(outbuf),1,0);
3022 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3023 start_index, max_count));
3026 print_queue_struct *queue = NULL;
3027 char *p = smb_buf(outbuf) + 3;
3028 int count = print_queue_status(SNUM(conn), &queue,NULL);
3029 int num_to_get = ABS(max_count);
3030 int first = (max_count>0?start_index:start_index+max_count+1);
3036 num_to_get = MIN(num_to_get,count-first);
3039 for (i=first;i<first+num_to_get;i++) {
3040 put_dos_date2(p,0,queue[i].time);
3041 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3042 SSVAL(p,5, queue[i].job);
3043 SIVAL(p,7,queue[i].size);
3045 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3050 outsize = set_message(outbuf,2,28*count+3,False);
3051 SSVAL(outbuf,smb_vwv0,count);
3052 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3053 CVAL(smb_buf(outbuf),0) = 1;
3054 SSVAL(smb_buf(outbuf),1,28*count);
3059 DEBUG(3,("%d entries returned in queue\n",count));
3062 END_PROFILE(SMBsplretq);
3067 /****************************************************************************
3068 reply to a printwrite
3069 ****************************************************************************/
3070 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3073 int outsize = set_message(outbuf,0,0,True);
3075 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3076 START_PROFILE(SMBsplwr);
3078 if (!CAN_PRINT(conn)) {
3079 END_PROFILE(SMBsplwr);
3080 return ERROR_DOS(ERRDOS,ERRnoaccess);
3083 CHECK_FSP(fsp,conn);
3086 numtowrite = SVAL(smb_buf(inbuf),1);
3087 data = smb_buf(inbuf) + 3;
3089 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3090 END_PROFILE(SMBsplwr);
3091 return(UNIXERROR(ERRDOS,ERRnoaccess));
3094 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3096 END_PROFILE(SMBsplwr);
3101 /****************************************************************************
3102 The guts of the mkdir command, split out so it may be called by the NT SMB
3104 ****************************************************************************/
3105 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3107 BOOL bad_path = False;
3108 SMB_STRUCT_STAT sbuf;
3111 unix_convert(directory,conn,0,&bad_path,&sbuf);
3113 if (check_name(directory, conn))
3114 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3117 return map_nt_error_from_unix(errno);
3120 return NT_STATUS_OK;
3123 /****************************************************************************
3125 ****************************************************************************/
3127 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3132 START_PROFILE(SMBmkdir);
3134 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3136 status = mkdir_internal(conn, directory);
3137 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
3139 outsize = set_message(outbuf,0,0,True);
3141 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3143 END_PROFILE(SMBmkdir);
3147 /****************************************************************************
3148 Static function used by reply_rmdir to delete an entire directory
3149 tree recursively. Return False on ok, True on fail.
3150 ****************************************************************************/
3152 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3156 void *dirptr = OpenDir(conn, directory, False);
3161 while((dname = ReadDirName(dirptr))) {
3165 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3168 /* Construct the full name. */
3169 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3175 pstrcpy(fullname, directory);
3176 pstrcat(fullname, "/");
3177 pstrcat(fullname, dname);
3179 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
3184 if(st.st_mode & S_IFDIR) {
3185 if(recursive_rmdir(conn, fullname)!=0) {
3189 if(vfs_rmdir(conn,fullname) != 0) {
3193 } else if(vfs_unlink(conn,fullname) != 0) {
3202 /****************************************************************************
3203 The internals of the rmdir code - called elsewhere.
3204 ****************************************************************************/
3206 BOOL rmdir_internals(connection_struct *conn, char *directory)
3210 ok = (vfs_rmdir(conn,directory) == 0);
3211 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3213 * Check to see if the only thing in this directory are
3214 * vetoed files/directories. If so then delete them and
3215 * retry. If we fail to delete any of them (and we *don't*
3216 * do a recursive delete) then fail the rmdir.
3218 BOOL all_veto_files = True;
3220 void *dirptr = OpenDir(conn, directory, False);
3222 if(dirptr != NULL) {
3223 int dirpos = TellDir(dirptr);
3224 while ((dname = ReadDirName(dirptr))) {
3225 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3227 if(!IS_VETO_PATH(conn, dname)) {
3228 all_veto_files = False;
3233 if(all_veto_files) {
3234 SeekDir(dirptr,dirpos);
3235 while ((dname = ReadDirName(dirptr))) {
3239 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3242 /* Construct the full name. */
3243 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3248 pstrcpy(fullname, directory);
3249 pstrcat(fullname, "/");
3250 pstrcat(fullname, dname);
3252 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3254 if(st.st_mode & S_IFDIR) {
3255 if(lp_recursive_veto_delete(SNUM(conn))) {
3256 if(recursive_rmdir(conn, fullname) != 0)
3259 if(vfs_rmdir(conn,fullname) != 0)
3261 } else if(vfs_unlink(conn,fullname) != 0)
3265 /* Retry the rmdir */
3266 ok = (vfs_rmdir(conn,directory) == 0);
3276 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3281 /****************************************************************************
3283 ****************************************************************************/
3285 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3290 BOOL bad_path = False;
3291 SMB_STRUCT_STAT sbuf;
3292 START_PROFILE(SMBrmdir);
3294 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3296 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3298 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3300 if (check_name(directory,conn))
3302 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3303 ok = rmdir_internals(conn, directory);
3308 if((errno == ENOENT) && bad_path)
3310 unix_ERR_class = ERRDOS;
3311 unix_ERR_code = ERRbadpath;
3313 END_PROFILE(SMBrmdir);
3314 return(UNIXERROR(ERRDOS,ERRbadpath));
3317 outsize = set_message(outbuf,0,0,True);
3319 DEBUG( 3, ( "rmdir %s\n", directory ) );
3321 END_PROFILE(SMBrmdir);
3326 /*******************************************************************
3327 resolve wildcards in a filename rename
3328 ********************************************************************/
3329 static BOOL resolve_wildcards(char *name1,char *name2)
3331 fstring root1,root2;
3335 name1 = strrchr_m(name1,'/');
3336 name2 = strrchr_m(name2,'/');
3338 if (!name1 || !name2) return(False);
3340 fstrcpy(root1,name1);
3341 fstrcpy(root2,name2);
3342 p = strrchr_m(root1,'.');
3349 p = strrchr_m(root2,'.');
3381 pstrcpy(name2,root2);
3384 pstrcat(name2,ext2);
3390 /*******************************************************************
3391 check if a user is allowed to rename a file
3392 ********************************************************************/
3393 static BOOL can_rename(char *fname,connection_struct *conn)
3395 SMB_STRUCT_STAT sbuf;
3397 if (!CAN_WRITE(conn)) return(False);
3399 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3400 if (!check_file_sharing(conn,fname,True)) return(False);
3404 /****************************************************************************
3405 The guts of the rename command, split out so it may be called by the NT SMB
3407 ****************************************************************************/
3408 NTSTATUS rename_internals(connection_struct *conn,
3410 char *newname, BOOL replace_if_exists)
3414 pstring newname_last_component;
3417 BOOL bad_path1 = False;
3418 BOOL bad_path2 = False;
3420 NTSTATUS error = NT_STATUS_OK;
3423 SMB_STRUCT_STAT sbuf1, sbuf2;
3425 *directory = *mask = 0;
3427 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3428 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3431 * Split the old name into directory and last component
3432 * strings. Note that unix_convert may have stripped off a
3433 * leading ./ from both name and newname if the rename is
3434 * at the root of the share. We need to make sure either both
3435 * name and newname contain a / character or neither of them do
3436 * as this is checked in resolve_wildcards().
3439 p = strrchr_m(name,'/');
3441 pstrcpy(directory,".");
3445 pstrcpy(directory,name);
3447 *p = '/'; /* Replace needed for exceptional test below. */
3451 * We should only check the mangled cache
3452 * here if unix_convert failed. This means
3453 * that the path in 'mask' doesn't exist
3454 * on the file system and so we need to look
3455 * for a possible mangle. This patch from
3456 * Tine Smukavec <valentin.smukavec@hermes.si>.
3459 if (!rc && is_mangled(mask))
3460 check_mangled_cache( mask );
3462 has_wild = ms_has_wild(mask);
3466 * No wildcards - just process the one file.
3468 BOOL is_short_name = is_8_3(name, True);
3470 /* Add a terminating '/' to the directory name. */
3471 pstrcat(directory,"/");
3472 pstrcat(directory,mask);
3474 /* Ensure newname contains a '/' also */
3475 if(strrchr_m(newname,'/') == 0) {
3478 pstrcpy(tmpstr, "./");
3479 pstrcat(tmpstr, newname);
3480 pstrcpy(newname, tmpstr);
3483 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",
3484 case_sensitive, case_preserve, short_case_preserve, directory,
3485 newname, newname_last_component, is_short_name));
3488 * Check for special case with case preserving and not
3489 * case sensitive, if directory and newname are identical,
3490 * and the old last component differs from the original
3491 * last component only by case, then we should allow
3492 * the rename (user is trying to change the case of the
3495 if((case_sensitive == False) &&
3496 (((case_preserve == True) &&
3497 (is_short_name == False)) ||
3498 ((short_case_preserve == True) &&
3499 (is_short_name == True))) &&
3500 strcsequal(directory, newname)) {
3501 pstring newname_modified_last_component;
3504 * Get the last component of the modified name.
3505 * Note that we guarantee that newname contains a '/'
3508 p = strrchr_m(newname,'/');
3509 pstrcpy(newname_modified_last_component,p+1);
3511 if(strcsequal(newname_modified_last_component,
3512 newname_last_component) == False) {
3514 * Replace the modified last component with
3517 pstrcpy(p+1, newname_last_component);
3521 if(replace_if_exists) {
3523 * NT SMB specific flag - rename can overwrite
3524 * file with the same name so don't check for
3528 if(resolve_wildcards(directory,newname) &&
3529 can_rename(directory,conn) &&
3530 conn->vfs_ops.rename(conn,directory,newname) == 0)
3533 if (resolve_wildcards(directory,newname) &&
3534 can_rename(directory,conn) &&
3535 !vfs_file_exist(conn,newname,NULL) &&
3536 conn->vfs_ops.rename(conn,directory,newname) == 0)
3540 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3541 directory,newname));
3543 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3544 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3546 error = NT_STATUS_OBJECT_NAME_COLLISION;
3550 * Wildcards - process each file that matches.
3552 void *dirptr = NULL;
3556 if (check_name(directory,conn))
3557 dirptr = OpenDir(conn, directory, True);
3560 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3562 if (strequal(mask,"????????.???"))
3565 while ((dname = ReadDirName(dirptr))) {
3568 pstrcpy(fname,dname);
3570 if(!mask_match(fname, mask, case_sensitive))
3573 error = NT_STATUS_ACCESS_DENIED;
3574 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3575 if (!can_rename(fname,conn)) {
3576 DEBUG(6,("rename %s refused\n", fname));
3579 pstrcpy(destname,newname);
3581 if (!resolve_wildcards(fname,destname)) {
3582 DEBUG(6,("resolve_wildcards %s %s failed\n",
3587 if (!replace_if_exists &&
3588 vfs_file_exist(conn,destname, NULL)) {
3589 DEBUG(6,("file_exist %s\n", destname));
3590 error = NT_STATUS_OBJECT_NAME_COLLISION;
3594 if (!conn->vfs_ops.rename(conn,fname,destname))
3596 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3602 if (count == 0 && NT_STATUS_IS_OK(error)) {
3603 error = map_nt_error_from_unix(errno);
3609 /****************************************************************************
3611 ****************************************************************************/
3613 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3622 START_PROFILE(SMBmv);
3624 p = smb_buf(inbuf) + 1;
3625 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3627 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3629 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3630 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3632 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3634 status = rename_internals(conn, name, newname, False);
3635 if (!NT_STATUS_IS_OK(status)) {
3636 return ERROR_NT(status);
3640 * Win2k needs a changenotify request response before it will
3641 * update after a rename..
3643 process_pending_change_notify_queue((time_t)0);
3644 outsize = set_message(outbuf,0,0,True);
3650 /*******************************************************************
3651 Copy a file as part of a reply_copy.
3652 ******************************************************************/
3654 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3655 int count,BOOL target_is_directory, int *err_ret)
3658 SMB_STRUCT_STAT src_sbuf, sbuf2;
3660 files_struct *fsp1,*fsp2;
3665 pstrcpy(dest,dest1);
3666 if (target_is_directory) {
3667 char *p = strrchr_m(src,'/');
3676 if (!vfs_file_exist(conn,src,&src_sbuf))
3679 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3680 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3685 if (!target_is_directory && count)
3686 ofun = FILE_EXISTS_OPEN;
3688 if (vfs_stat(conn,dest,&sbuf2) == -1)
3689 ZERO_STRUCTP(&sbuf2);
3691 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3692 ofun,src_sbuf.st_mode,0,&Access,&action);
3695 close_file(fsp1,False);
3699 if ((ofun&3) == 1) {
3700 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3701 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3703 * Stop the copy from occurring.
3706 src_sbuf.st_size = 0;
3710 if (src_sbuf.st_size)
3711 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3713 close_file(fsp1,False);
3715 * As we are opening fsp1 read-only we only expect
3716 * an error on close on fsp2 if we are out of space.
3717 * Thus we don't look at the error return from the
3720 *err_ret = close_file(fsp2,False);
3722 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3725 /****************************************************************************
3726 reply to a file copy.
3727 ****************************************************************************/
3728 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3733 pstring mask,newname;
3736 int error = ERRnoaccess;
3740 int tid2 = SVAL(inbuf,smb_vwv0);
3741 int ofun = SVAL(inbuf,smb_vwv1);
3742 int flags = SVAL(inbuf,smb_vwv2);
3743 BOOL target_is_directory=False;
3744 BOOL bad_path1 = False;
3745 BOOL bad_path2 = False;
3747 SMB_STRUCT_STAT sbuf1, sbuf2;
3748 START_PROFILE(SMBcopy);
3750 *directory = *mask = 0;
3753 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3754 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3756 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3758 if (tid2 != conn->cnum) {
3759 /* can't currently handle inter share copies XXXX */
3760 DEBUG(3,("Rejecting inter-share copy\n"));
3761 END_PROFILE(SMBcopy);
3762 return ERROR_DOS(ERRSRV,ERRinvdevice);
3765 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3766 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3768 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3769 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3771 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3773 if ((flags&1) && target_is_directory) {
3774 END_PROFILE(SMBcopy);
3775 return ERROR_DOS(ERRDOS,ERRbadfile);
3778 if ((flags&2) && !target_is_directory) {
3779 END_PROFILE(SMBcopy);
3780 return ERROR_DOS(ERRDOS,ERRbadpath);
3783 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3784 /* wants a tree copy! XXXX */
3785 DEBUG(3,("Rejecting tree copy\n"));
3786 END_PROFILE(SMBcopy);
3787 return ERROR_DOS(ERRSRV,ERRerror);
3790 p = strrchr_m(name,'/');
3792 pstrcpy(directory,"./");
3796 pstrcpy(directory,name);
3801 * We should only check the mangled cache
3802 * here if unix_convert failed. This means
3803 * that the path in 'mask' doesn't exist
3804 * on the file system and so we need to look
3805 * for a possible mangle. This patch from
3806 * Tine Smukavec <valentin.smukavec@hermes.si>.
3809 if (!rc && is_mangled(mask))
3810 check_mangled_cache( mask );
3812 has_wild = ms_has_wild(mask);
3815 pstrcat(directory,"/");
3816 pstrcat(directory,mask);
3817 if (resolve_wildcards(directory,newname) &&
3818 copy_file(directory,newname,conn,ofun,
3819 count,target_is_directory,&err)) count++;
3822 END_PROFILE(SMBcopy);
3823 return(UNIXERROR(ERRHRD,ERRgeneral));
3825 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3827 void *dirptr = NULL;
3831 if (check_name(directory,conn))
3832 dirptr = OpenDir(conn, directory, True);
3837 if (strequal(mask,"????????.???"))
3840 while ((dname = ReadDirName(dirptr))) {
3842 pstrcpy(fname,dname);
3844 if(!mask_match(fname, mask, case_sensitive))
3847 error = ERRnoaccess;
3848 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3849 pstrcpy(destname,newname);
3850 if (resolve_wildcards(fname,destname) &&
3851 copy_file(fname,destname,conn,ofun,
3852 count,target_is_directory,&err)) count++;
3853 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3861 /* Error on close... */
3863 END_PROFILE(SMBcopy);
3864 return(UNIXERROR(ERRHRD,ERRgeneral));
3868 END_PROFILE(SMBcopy);
3869 return ERROR_DOS(ERRDOS,error);
3872 if((errno == ENOENT) && (bad_path1 || bad_path2))
3874 unix_ERR_class = ERRDOS;
3875 unix_ERR_code = ERRbadpath;
3877 END_PROFILE(SMBcopy);
3878 return(UNIXERROR(ERRDOS,error));
3882 outsize = set_message(outbuf,1,0,True);
3883 SSVAL(outbuf,smb_vwv0,count);
3885 END_PROFILE(SMBcopy);
3889 /****************************************************************************
3891 ****************************************************************************/
3892 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3898 START_PROFILE(pathworks_setdir);
3901 if (!CAN_SETDIR(snum)) {
3902 END_PROFILE(pathworks_setdir);
3903 return ERROR_DOS(ERRDOS,ERRnoaccess);
3906 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
3908 if (strlen(newdir) == 0) {
3911 ok = vfs_directory_exist(conn,newdir,NULL);
3913 string_set(&conn->connectpath,newdir);
3918 END_PROFILE(pathworks_setdir);
3919 return ERROR_DOS(ERRDOS,ERRbadpath);
3922 outsize = set_message(outbuf,0,0,True);
3923 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3925 DEBUG(3,("setdir %s\n", newdir));
3927 END_PROFILE(pathworks_setdir);
3931 /****************************************************************************
3932 Get a lock pid, dealing with large count requests.
3933 ****************************************************************************/
3935 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3937 if(!large_file_format)
3938 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3940 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
3943 /****************************************************************************
3944 Get a lock count, dealing with large count requests.
3945 ****************************************************************************/
3947 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3949 SMB_BIG_UINT count = 0;
3951 if(!large_file_format) {
3952 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3955 #if defined(HAVE_LONGLONG)
3956 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3957 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3958 #else /* HAVE_LONGLONG */
3961 * NT4.x seems to be broken in that it sends large file (64 bit)
3962 * lockingX calls even if the CAP_LARGE_FILES was *not*
3963 * negotiated. For boxes without large unsigned ints truncate the
3964 * lock count by dropping the top 32 bits.
3967 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3968 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3969 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3970 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3971 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3974 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3975 #endif /* HAVE_LONGLONG */
3981 #if !defined(HAVE_LONGLONG)
3982 /****************************************************************************
3983 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3984 ****************************************************************************/
3985 static uint32 map_lock_offset(uint32 high, uint32 low)
3989 uint32 highcopy = high;
3992 * Try and find out how many significant bits there are in high.
3995 for(i = 0; highcopy; i++)
3999 * We use 31 bits not 32 here as POSIX
4000 * lock offsets may not be negative.
4003 mask = (~0) << (31 - i);
4006 return 0; /* Fail. */
4012 #endif /* !defined(HAVE_LONGLONG) */
4014 /****************************************************************************
4015 Get a lock offset, dealing with large offset requests.
4016 ****************************************************************************/
4018 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4020 SMB_BIG_UINT offset = 0;
4024 if(!large_file_format) {
4025 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4028 #if defined(HAVE_LONGLONG)
4029 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4030 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4031 #else /* HAVE_LONGLONG */
4034 * NT4.x seems to be broken in that it sends large file (64 bit)
4035 * lockingX calls even if the CAP_LARGE_FILES was *not*
4036 * negotiated. For boxes without large unsigned ints mangle the
4037 * lock offset by mapping the top 32 bits onto the lower 32.
4040 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4041 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4042 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4045 if((new_low = map_lock_offset(high, low)) == 0) {
4047 return (SMB_BIG_UINT)-1;
4050 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4051 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4052 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4053 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4056 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4057 #endif /* HAVE_LONGLONG */
4063 /****************************************************************************
4064 reply to a lockingX request
4065 ****************************************************************************/
4067 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4069 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4070 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4071 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4072 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4073 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4074 SMB_BIG_UINT count = 0, offset = 0;
4076 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4079 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4083 START_PROFILE(SMBlockingX);
4085 CHECK_FSP(fsp,conn);
4087 data = smb_buf(inbuf);
4089 /* Check if this is an oplock break on a file
4090 we have granted an oplock on.
4092 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4093 /* Client can insist on breaking to none. */
4094 BOOL break_to_none = (oplocklevel == 0);
4096 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4097 (unsigned int)oplocklevel, fsp->fnum ));
4100 * Make sure we have granted an exclusive or batch oplock on this file.
4103 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4104 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4105 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4107 /* if this is a pure oplock break request then don't send a reply */
4108 if (num_locks == 0 && num_ulocks == 0) {
4109 END_PROFILE(SMBlockingX);
4112 END_PROFILE(SMBlockingX);
4113 return ERROR_DOS(ERRDOS,ERRlock);
4117 if (remove_oplock(fsp, break_to_none) == False) {
4118 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4122 /* if this is a pure oplock break request then don't send a reply */
4123 if (num_locks == 0 && num_ulocks == 0) {
4124 /* Sanity check - ensure a pure oplock break is not a
4126 if(CVAL(inbuf,smb_vwv0) != 0xff)
4127 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4128 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4129 END_PROFILE(SMBlockingX);
4135 * We do this check *after* we have checked this is not a oplock break
4136 * response message. JRA.
4139 release_level_2_oplocks_on_change(fsp);
4141 /* Data now points at the beginning of the list
4142 of smb_unlkrng structs */
4143 for(i = 0; i < (int)num_ulocks; i++) {
4144 lock_pid = get_lock_pid( data, i, large_file_format);
4145 count = get_lock_count( data, i, large_file_format);
4146 offset = get_lock_offset( data, i, large_file_format, &err);
4149 * There is no error code marked "stupid client bug".... :-).
4152 END_PROFILE(SMBlockingX);
4153 return ERROR_DOS(ERRDOS,ERRnoaccess);
4156 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4157 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4159 status = do_unlock(fsp,conn,lock_pid,count,offset);
4160 if (NT_STATUS_V(status)) {
4161 END_PROFILE(SMBlockingX);
4162 return ERROR_NT(status);
4166 /* Setup the timeout in seconds. */
4167 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4169 /* Now do any requested locks */
4170 data += ((large_file_format ? 20 : 10)*num_ulocks);
4172 /* Data now points at the beginning of the list
4173 of smb_lkrng structs */
4175 for(i = 0; i < (int)num_locks; i++) {
4176 lock_pid = get_lock_pid( data, i, large_file_format);
4177 count = get_lock_count( data, i, large_file_format);
4178 offset = get_lock_offset( data, i, large_file_format, &err);
4181 * There is no error code marked "stupid client bug".... :-).
4184 END_PROFILE(SMBlockingX);
4185 return ERROR_DOS(ERRDOS,ERRnoaccess);
4188 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4189 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4191 status = do_lock(fsp,conn,lock_pid, count,offset,
4192 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4193 if (NT_STATUS_V(status)) {
4194 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4196 * A blocking lock was requested. Package up
4197 * this smb into a queued request and push it
4198 * onto the blocking lock queue.
4200 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4201 END_PROFILE(SMBlockingX);
4209 /* If any of the above locks failed, then we must unlock
4210 all of the previous locks (X/Open spec). */
4211 if (i != num_locks && num_locks != 0) {
4213 * Ensure we don't do a remove on the lock that just failed,
4214 * as under POSIX rules, if we have a lock already there, we
4215 * will delete it (and we shouldn't) .....
4217 for(i--; i >= 0; i--) {
4218 lock_pid = get_lock_pid( data, i, large_file_format);
4219 count = get_lock_count( data, i, large_file_format);
4220 offset = get_lock_offset( data, i, large_file_format, &err);
4223 * There is no error code marked "stupid client bug".... :-).
4226 END_PROFILE(SMBlockingX);
4227 return ERROR_DOS(ERRDOS,ERRnoaccess);
4230 do_unlock(fsp,conn,lock_pid,count,offset);
4232 END_PROFILE(SMBlockingX);
4233 return ERROR_NT(status);
4236 set_message(outbuf,2,0,True);
4238 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4239 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4241 END_PROFILE(SMBlockingX);
4242 return chain_reply(inbuf,outbuf,length,bufsize);
4246 /****************************************************************************
4247 reply to a SMBreadbmpx (read block multiplex) request
4248 ****************************************************************************/
4249 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4260 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4261 START_PROFILE(SMBreadBmpx);
4263 /* this function doesn't seem to work - disable by default */
4264 if (!lp_readbmpx()) {
4265 END_PROFILE(SMBreadBmpx);
4266 return ERROR_DOS(ERRSRV,ERRuseSTD);
4269 outsize = set_message(outbuf,8,0,True);
4271 CHECK_FSP(fsp,conn);
4274 startpos = IVAL(inbuf,smb_vwv1);
4275 maxcount = SVAL(inbuf,smb_vwv3);
4277 data = smb_buf(outbuf);
4278 pad = ((long)data)%4;
4279 if (pad) pad = 4 - pad;
4282 max_per_packet = bufsize-(outsize+pad);
4286 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4287 END_PROFILE(SMBreadBmpx);
4288 return ERROR_DOS(ERRDOS,ERRlock);
4293 size_t N = MIN(max_per_packet,tcount-total_read);
4295 nread = read_file(fsp,data,startpos,N);
4297 if (nread <= 0) nread = 0;
4299 if (nread < (ssize_t)N)
4300 tcount = total_read + nread;
4302 set_message(outbuf,8,nread,False);
4303 SIVAL(outbuf,smb_vwv0,startpos);
4304 SSVAL(outbuf,smb_vwv2,tcount);
4305 SSVAL(outbuf,smb_vwv6,nread);
4306 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4308 if (!send_smb(smbd_server_fd(),outbuf))
4309 exit_server("reply_readbmpx: send_smb failed.\n");
4311 total_read += nread;
4314 while (total_read < (ssize_t)tcount);
4316 END_PROFILE(SMBreadBmpx);
4321 /****************************************************************************
4322 reply to a SMBsetattrE
4323 ****************************************************************************/
4325 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4327 struct utimbuf unix_times;
4329 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4330 START_PROFILE(SMBsetattrE);
4332 outsize = set_message(outbuf,0,0,True);
4334 CHECK_FSP(fsp,conn);
4336 /* Convert the DOS times into unix times. Ignore create
4337 time as UNIX can't set this.
4339 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4340 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4343 * Patch from Ray Frush <frush@engr.colostate.edu>
4344 * Sometimes times are sent as zero - ignore them.
4347 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4349 /* Ignore request */
4352 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4353 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4355 END_PROFILE(SMBsetattrE);
4358 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4360 /* set modify time = to access time if modify time was 0 */
4361 unix_times.modtime = unix_times.actime;
4364 /* Set the date on this file */
4365 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4366 END_PROFILE(SMBsetattrE);
4367 return ERROR_DOS(ERRDOS,ERRnoaccess);
4370 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4371 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4373 END_PROFILE(SMBsetattrE);
4378 /****************************************************************************
4379 reply to a SMBgetattrE
4380 ****************************************************************************/
4382 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4384 SMB_STRUCT_STAT sbuf;
4387 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4388 START_PROFILE(SMBgetattrE);
4390 outsize = set_message(outbuf,11,0,True);
4392 CHECK_FSP(fsp,conn);
4394 /* Do an fstat on this file */
4395 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4396 END_PROFILE(SMBgetattrE);
4397 return(UNIXERROR(ERRDOS,ERRnoaccess));
4400 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4402 /* Convert the times into dos times. Set create
4403 date to be last modify date as UNIX doesn't save
4405 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4406 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4407 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4410 SIVAL(outbuf,smb_vwv6,0);
4411 SIVAL(outbuf,smb_vwv8,0);
4415 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4416 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4418 SSVAL(outbuf,smb_vwv10, mode);
4420 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4422 END_PROFILE(SMBgetattrE);