/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
Main SMB reply routines
Copyright (C) Andrew Tridgell 1992-1998
-
+ Copyright (C) Andrew Bartlett 2001
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
/* look in server.c for some explanation of these variables */
extern int Protocol;
-extern int DEBUGLEVEL;
extern int max_send;
extern int max_recv;
extern char magic_char;
extern BOOL case_sensitive;
extern BOOL case_preserve;
extern BOOL short_case_preserve;
-extern userdom_struct current_user_info;
extern pstring global_myname;
extern int global_oplock_break;
-uint32 global_client_caps = 0;
unsigned int smb_echo_count = 0;
-/****************************************************************************
-report a possible attack via the password buffer overflow bug
-****************************************************************************/
-
-static void overflow_attack(int len)
-{
- if( DEBUGLVL( 0 ) ) {
- dbgtext( "ERROR: Invalid password length %d.\n", len );
- dbgtext( "Your machine may be under attack by someone " );
- dbgtext( "attempting to exploit an old bug.\n" );
- dbgtext( "Attack was from IP = %s.\n", client_addr() );
- }
-}
+extern fstring remote_machine;
+extern BOOL global_encrypted_passwords_negotiated;
/****************************************************************************
int msg_type = CVAL(inbuf,0);
int msg_flags = CVAL(inbuf,1);
pstring name1,name2;
- extern fstring remote_machine;
+
extern fstring local_machine;
int len;
char name_type = 0;
switch (msg_type) {
case 0x81: /* session request */
- CVAL(outbuf,0) = 0x82;
- CVAL(outbuf,3) = 0;
+ SCVAL(outbuf,0,0x82);
+ SCVAL(outbuf,3,0);
if (name_len(inbuf+4) > 50 ||
name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
DEBUG(0,("Invalid name length in session request\n"));
if (name_type == 'R') {
/* We are being asked for a pathworks session ---
no thanks! */
- CVAL(outbuf, 0) = 0x83;
+ SCVAL(outbuf, 0,0x83);
break;
}
case 0x89: /* session keepalive request
(some old clients produce this?) */
- CVAL(outbuf,0) = 0x85;
- CVAL(outbuf,3) = 0;
+ SCVAL(outbuf,0,SMBkeepalive);
+ SCVAL(outbuf,3,0);
break;
case 0x82: /* positive session response */
DEBUG(0,("Unexpected session response\n"));
break;
- case 0x85: /* session keepalive */
+ case SMBkeepalive: /* session keepalive */
default:
return(0);
}
}
-/*******************************************************************
-work out what error to give to a failed connection
-********************************************************************/
-
-static int connection_error(char *inbuf,char *outbuf,int ecode)
-{
- if (ecode == ERRnoipc || ecode == ERRnosuchshare)
- return(ERROR(ERRDOS,ecode));
-
- return(ERROR(ERRSRV,ecode));
-}
-
-
/****************************************************************************
Reply to a tcon.
****************************************************************************/
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
pstring service;
- pstring user;
pstring password;
pstring dev;
int outsize = 0;
uint16 vuid = SVAL(inbuf,smb_uid);
int pwlen=0;
- int ecode = -1;
+ NTSTATUS nt_status;
char *p;
-
+ DATA_BLOB password_blob;
+
START_PROFILE(SMBtcon);
- *service = *user = *password = *dev = 0;
+ *service = *password = *dev = 0;
p = smb_buf(inbuf)+1;
- p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
- p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
- p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
-
- *user = 0;
- p = strchr_m(service,'%');
- if (p != NULL) {
- *p = 0;
- fstrcpy(user,p+1);
- }
+ p += srvstr_pull_buf(inbuf, service, p, sizeof(service), STR_TERMINATE) + 1;
+ pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
+ p += pwlen;
+ p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
p = strrchr_m(service,'\\');
if (p) {
pstrcpy(service, p+1);
}
- /*
- * If the vuid is valid, we should be using that....
- */
+ password_blob = data_blob(password, pwlen+1);
- if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
- pstrcpy(user,validated_username(vuid));
- } else {
-
- /*
- * Pass the user through the NT -> unix user mapping
- * function.
- */
-
- (void)map_username(user);
-
- /*
- * Do any UNIX username case mangling.
- */
- (void)Get_Pwnam( user, True);
- }
+ conn = make_connection(service,password_blob,dev,vuid,&nt_status);
- conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
+ data_blob_clear_free(&password_blob);
if (!conn) {
END_PROFILE(SMBtcon);
- return(connection_error(inbuf,outbuf,ecode));
+ return ERROR_NT(nt_status);
}
outsize = set_message(outbuf,2,0,True);
SSVAL(outbuf,smb_vwv1,conn->cnum);
SSVAL(outbuf,smb_tid,conn->cnum);
- DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
- service, user, conn->cnum));
+ DEBUG(3,("tcon service=%s cnum=%d\n",
+ service, conn->cnum));
END_PROFILE(SMBtcon);
return(outsize);
int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
fstring service;
- pstring user;
- pstring password;
+ DATA_BLOB password;
pstring devicename;
- int ecode = -1;
+ NTSTATUS nt_status;
uint16 vuid = SVAL(inbuf,smb_uid);
int passlen = SVAL(inbuf,smb_vwv3);
pstring path;
char *p, *q;
- START_PROFILE(SMBtconX);
-
- *service = *user = *password = *devicename = 0;
+ extern BOOL global_encrypted_passwords_negotiated;
+ START_PROFILE(SMBtconX);
+
+ *service = *devicename = 0;
/* we might have to close an old one */
if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
}
if (passlen > MAX_PASS_LEN) {
- overflow_attack(passlen);
- return(ERROR(ERRDOS,ERRbuftoosmall));
+ return ERROR_DOS(ERRDOS,ERRbuftoosmall);
}
- memcpy(password,smb_buf(inbuf),passlen);
- password[passlen]=0;
- p = smb_buf(inbuf) + passlen;
- p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
-
- if (passlen != 24) {
- if (strequal(password," "))
- *password = 0;
- passlen = strlen(password);
+ if (global_encrypted_passwords_negotiated) {
+ password = data_blob(smb_buf(inbuf),passlen);
+ } else {
+ password = data_blob(smb_buf(inbuf),passlen+1);
+ /* Ensure correct termination */
+ password.data[passlen]=0;
}
-
+
+ p = smb_buf(inbuf) + passlen;
+ p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
/*
* the service name can be either: \\server\share
q = strchr_m(path+2,'\\');
if (!q) {
END_PROFILE(SMBtconX);
- return(ERROR(ERRDOS,ERRnosuchshare));
+ return(ERROR_DOS(ERRDOS,ERRnosuchshare));
}
fstrcpy(service,q+1);
}
else
fstrcpy(service,path);
- q = strchr_m(service,'%');
- if (q) {
- *q++ = 0;
- fstrcpy(user,q);
- }
p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
DEBUG(4,("Got device type %s\n",devicename));
- /*
- * If the vuid is valid, we should be using that....
- */
-
- if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
- pstrcpy(user,validated_username(vuid));
- } else {
-
- /*
- * Pass the user through the NT -> unix user mapping
- * function.
- */
-
- (void)map_username(user);
-
- /*
- * Do any UNIX username case mangling.
- */
- (void)Get_Pwnam(user, True);
-
- }
-
- conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
+ conn = make_connection(service,password,devicename,vuid,&nt_status);
+ data_blob_clear_free(&password);
+
if (!conn) {
END_PROFILE(SMBtconX);
- return(connection_error(inbuf,outbuf,ecode));
+ return ERROR_NT(nt_status);
}
if (Protocol < PROTOCOL_NT1) {
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
- SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
+ SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
+ (lp_csc_policy(SNUM(conn)) << 2));
init_dfsroot(conn, inbuf, outbuf);
}
- DEBUG(3,("tconX service=%s user=%s\n",
- service, user));
+ DEBUG(3,("tconX service=%s \n",
+ service));
/* set the incoming and outgoing tid to the just created one */
SSVAL(inbuf,smb_tid,conn->cnum);
DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
smb_fn_name(type), type, type));
- return(ERROR(ERRSRV,ERRunknownsmb));
+ return(ERROR_DOS(ERRSRV,ERRunknownsmb));
}
break;
default:
END_PROFILE(SMBioctl);
- return(ERROR(ERRSRV,ERRnosupport));
+ return(ERROR_DOS(ERRSRV,ERRnosupport));
}
outsize = set_message(outbuf,8,replysize+1,True);
return outsize;
}
-/****************************************************************************
- This function breaks the authentication split. It needs sorting out.
- I can't see why we can't hadle this INSIDE the check_password, as in then
- end all it does it spit out an nt_status code.
- ****************************************************************************/
-/****************************************************************************
- always return an error: it's just a matter of which one...
- ****************************************************************************/
-static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
- char *smb_passwd, int smb_passlen,
- char *smb_nt_passwd, int smb_nt_passlen)
-{
- /* check if trust account exists */
- SAM_ACCOUNT *sam_trust_acct = NULL;
- uint16 acct_ctrl;
- BOOL ret;
- auth_usersupplied_info user_info;
- auth_serversupplied_info server_info;
- AUTH_STR domain, smb_username, wksta_name;
-
- ZERO_STRUCT(user_info);
- ZERO_STRUCT(server_info);
- ZERO_STRUCT(domain);
- ZERO_STRUCT(smb_username);
- ZERO_STRUCT(wksta_name);
-
- domain.str = lp_workgroup();
- domain.len = strlen(domain.str);
-
- user_info.requested_domain = domain;
- user_info.domain = domain;
-
- smb_username.str = user;
- smb_username.len = strlen(smb_username.str);
-
- user_info.requested_username = smb_username; /* For the time-being */
- user_info.smb_username = smb_username;
-
- user_info.wksta_name = wksta_name;
-
- user_info.lm_resp.buffer = (uint8 *)smb_passwd;
- user_info.lm_resp.len = smb_passlen;
- user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd;
- user_info.nt_resp.len = smb_nt_passlen;
-
- if (!last_challenge(user_info.chal)) {
- DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
- return NT_STATUS_LOGON_FAILURE;
- }
-
- pdb_init_sam(&sam_trust_acct);
-
- if (lp_security() == SEC_USER) {
- ret = pdb_getsampwnam(sam_trust_acct, user);
- } else {
- DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- pdb_free_sam(sam_trust_acct);
- return(ERROR(0, NT_STATUS_LOGON_FAILURE));
- }
-
- if (ret == False) {
- /* lkclXXXX: workstation entry doesn't exist */
- DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- pdb_free_sam(sam_trust_acct);
- return(ERROR(0, NT_STATUS_NO_SUCH_USER));
- } else {
- if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
- DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- pdb_free_sam(sam_trust_acct);
- return(ERROR(0, NT_STATUS_LOGON_FAILURE));
- }
-
- if (!smb_password_ok(sam_trust_acct, &user_info, &server_info)) {
- DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- pdb_free_sam(sam_trust_acct);
- return(ERROR(0, NT_STATUS_LOGON_FAILURE));
- }
-
- acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
- pdb_free_sam(sam_trust_acct);
- if (acct_ctrl & ACB_DOMTRUST) {
- DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
- }
-
- if (acct_ctrl & ACB_SVRTRUST) {
- DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
- }
-
- if (acct_ctrl & ACB_WSTRUST) {
- DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
- }
- }
-
- /* don't know what to do: indicate logon failure */
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return(ERROR(0, NT_STATUS_LOGON_FAILURE));
-}
-
-/****************************************************************************
- Return a bad password error configured for the correct client type.
-****************************************************************************/
-
-static int bad_password_error(char *inbuf,char *outbuf)
-{
-
- if (global_client_caps & CAP_STATUS32) {
- SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return(ERROR(0,NT_STATUS_LOGON_FAILURE));
- }
-
- return(ERROR(ERRSRV,ERRbadpw));
-}
-
-/****************************************************************************
-reply to a session setup command
-****************************************************************************/
-
-int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
-{
- int sess_vuid;
- gid_t gid;
- uid_t uid;
- char* full_name;
- int smb_bufsize;
- int smb_apasslen = 0;
- pstring smb_apasswd;
- int smb_ntpasslen = 0;
- pstring smb_ntpasswd;
- BOOL valid_password = False;
- pstring user;
- pstring orig_user;
- fstring domain;
- fstring native_os;
- fstring native_lanman;
- BOOL guest=False;
- static BOOL done_sesssetup = False;
- BOOL doencrypt = SMBENCRYPT();
- START_PROFILE(SMBsesssetupX);
-
- *smb_apasswd = 0;
- *smb_ntpasswd = 0;
-
- smb_bufsize = SVAL(inbuf,smb_vwv2);
-
- if (Protocol < PROTOCOL_NT1) {
- smb_apasslen = SVAL(inbuf,smb_vwv7);
- if (smb_apasslen > MAX_PASS_LEN) {
- overflow_attack(smb_apasslen);
- return(ERROR(ERRDOS,ERRbuftoosmall));
- }
-
- memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
- srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
-
- if (!doencrypt && (lp_security() != SEC_SERVER)) {
- smb_apasslen = strlen(smb_apasswd);
- }
- } else {
- uint16 passlen1 = SVAL(inbuf,smb_vwv7);
- uint16 passlen2 = SVAL(inbuf,smb_vwv8);
- enum remote_arch_types ra_type = get_remote_arch();
- char *p = smb_buf(inbuf);
-
- if(global_client_caps == 0)
- global_client_caps = IVAL(inbuf,smb_vwv11);
-
- /* client_caps is used as final determination if client is NT or Win95.
- This is needed to return the correct error codes in some
- circumstances.
- */
-
- if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
- if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
- set_remote_arch( RA_WIN95);
- }
- }
-
- if (passlen1 != 24 && passlen2 != 24)
- doencrypt = False;
-
- if (passlen1 > MAX_PASS_LEN) {
- overflow_attack(passlen1);
- return(ERROR(ERRDOS,ERRbuftoosmall));
- }
-
- passlen1 = MIN(passlen1, MAX_PASS_LEN);
- passlen2 = MIN(passlen2, MAX_PASS_LEN);
-
- if (!doencrypt) {
- /* both Win95 and WinNT stuff up the password lengths for
- non-encrypting systems. Uggh.
-
- if passlen1==24 its a win95 system, and its setting the
- password length incorrectly. Luckily it still works with the
- default code because Win95 will null terminate the password
- anyway
-
- if passlen1>0 and passlen2>0 then maybe its a NT box and its
- setting passlen2 to some random value which really stuffs
- things up. we need to fix that one. */
-
- if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
- passlen2 = 0;
- }
-
- if (lp_restrict_anonymous()) {
- /* there seems to be no reason behind the differences in MS clients formatting
- * various info like the domain, NativeOS, and NativeLanMan fields. Win95
- * in particular seems to have an extra null byte between the username and the
- * domain, or the password length calculation is wrong, which throws off the
- * string extraction routines below. This makes the value of domain be the
- * empty string, which fails the restrict anonymous check further down.
- * This compensates for that, and allows browsing to work in mixed NT and
- * win95 environments even when restrict anonymous is true. AAB
- */
- dump_data(100, p, 0x70);
- DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
- if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
- DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
- DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
- DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
- passlen1 = 1;
- }
- }
-
- if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
- /* Save the lanman2 password and the NT md4 password. */
- smb_apasslen = passlen1;
- memcpy(smb_apasswd,p,smb_apasslen);
- smb_apasswd[smb_apasslen] = 0;
- smb_ntpasslen = passlen2;
- memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
- smb_ntpasswd[smb_ntpasslen] = 0;
- } else {
- /* we use the first password that they gave */
- smb_apasslen = passlen1;
- StrnCpy(smb_apasswd,p,smb_apasslen);
-
- /* trim the password */
- smb_apasslen = strlen(smb_apasswd);
-
- /* wfwg sometimes uses a space instead of a null */
- if (strequal(smb_apasswd," ")) {
- smb_apasslen = 0;
- *smb_apasswd = 0;
- }
- }
-
- p += passlen1 + passlen2;
- p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
- STR_TERMINATE);
- /*
- * Incoming user and domain are in DOS codepage format. Convert
- * to UNIX.
- */
- p += srvstr_pull(inbuf, domain, p, sizeof(domain),
- -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
- -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
- -1, STR_TERMINATE);
- DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
- domain,native_os,native_lanman));
- }
-
- /* don't allow for weird usernames or domains */
- alpha_strcpy(user, user, ". _-$", sizeof(user));
- alpha_strcpy(domain, domain, ". _-", sizeof(domain));
- if (strstr(user, "..") || strstr(domain,"..")) {
- return bad_password_error(inbuf, outbuf);
- }
-
- if (lp_security() == SEC_SHARE) {
- /* in share level we should ignore any passwords */
- smb_ntpasslen = 0;
- smb_apasslen = 0;
- guest = True;
- }
-
-
- DEBUG(3,("sesssetupX:name=[%s]\n",user));
-
- /* If name ends in $ then I think it's asking about whether a */
- /* computer with that name (minus the $) has access. For now */
- /* say yes to everything ending in $. */
-
- if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
- END_PROFILE(SMBsesssetupX);
- return session_trust_account(conn, inbuf, outbuf, user,
- smb_apasswd, smb_apasslen,
- smb_ntpasswd, smb_ntpasslen);
- }
-
- if (done_sesssetup && lp_restrict_anonymous()) {
- /* tests show that even if browsing is done over already validated connections
- * without a username and password the domain is still provided, which it
- * wouldn't be if it was a purely anonymous connection. So, in order to
- * restrict anonymous, we only deny connections that have no session
- * information. If a domain has been provided, then it's not a purely
- * anonymous connection. AAB
- */
- if (!*user && !*smb_apasswd && !*domain) {
- DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
- END_PROFILE(SMBsesssetupX);
- return(ERROR(ERRDOS,ERRnoaccess));
- }
- }
-
- /* If no username is sent use the guest account */
- if (!*user) {
- pstrcpy(user,lp_guestaccount(-1));
- guest = True;
- }
-
- pstrcpy(current_user_info.smb_name,user);
-
- reload_services(True);
-
- /*
- * Save the username before mapping. We will use
- * the original username sent to us for security=server
- * and security=domain checking.
- */
-
- pstrcpy( orig_user, user);
-
- /*
- * Always try the "DOMAIN\user" lookup first, as this is the most
- * specific case. If this fails then try the simple "user" lookup.
- * But don't do this for guests, as this is always a local user.
- */
-
- if (!guest) {
- pstring dom_user;
-
- /* Work out who's who */
-
- slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
- domain, lp_winbind_separator(), user);
-
- if (sys_getpwnam(dom_user) != NULL) {
- pstrcpy(user, dom_user);
- DEBUG(3,("Using unix username %s\n", dom_user));
- }
-
- /*
- * Pass the user through the NT -> unix user mapping
- * function.
- */
-
- (void)map_username(user);
-
- /*
- * Do any UNIX username case mangling.
- */
- smb_getpwnam(user, True);
- }
-
- add_session_user(user);
-
- if (!guest) {
- valid_password = (pass_check_smb(user, domain,
- (unsigned char *)smb_apasswd, smb_apasslen,
- (unsigned char *)smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO);
-
- /* The true branch will be executed if
- (1) the NT password failed (or was not tried), and
- (2) LanMan authentication failed (or was disabled)
- */
- if (!valid_password)
- {
- if (lp_security() >= SEC_USER)
- {
- if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
- {
- DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
- END_PROFILE(SMBsesssetupX);
- return bad_password_error(inbuf,outbuf);
- }
-
- if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
- {
- if (smb_getpwnam(user,True))
- {
- DEBUG(1,("Rejecting user '%s': bad password\n", user));
- END_PROFILE(SMBsesssetupX);
- return bad_password_error(inbuf,outbuf);
- }
- }
-
- /*
- * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
- * Then always map to guest account - as done below.
- */
- }
-
- if (*smb_apasswd || !smb_getpwnam(user,True))
- pstrcpy(user,lp_guestaccount(-1));
- DEBUG(3,("Registered username %s for guest access\n",user));
- guest = True;
- }
- }
-
- if (!smb_getpwnam(user,True)) {
- DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
- pstrcpy(user,lp_guestaccount(-1));
- guest = True;
- }
-
- if (!strequal(user,lp_guestaccount(-1)) &&
- lp_servicenumber(user) < 0)
- {
- add_home_service(user,get_user_home_dir(user));
- }
-
-
- /* it's ok - setup a reply */
- if (Protocol < PROTOCOL_NT1) {
- set_message(outbuf,3,0,True);
- } else {
- char *p;
- set_message(outbuf,3,0,True);
- p = smb_buf(outbuf);
- p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
- set_message_end(outbuf,p);
- /* perhaps grab OS version here?? */
- }
-
- /* Set the correct uid in the outgoing and incoming packets
- We will use this on future requests to determine which
- user we should become.
- */
- {
- const struct passwd *pw = smb_getpwnam(user,False);
- if (!pw) {
- DEBUG(1,("Username %s is invalid on this system\n",user));
- END_PROFILE(SMBsesssetupX);
- return bad_password_error(inbuf,outbuf);
- }
- gid = pw->pw_gid;
- uid = pw->pw_uid;
- full_name = pw->pw_gecos;
- }
-
- if (guest)
- SSVAL(outbuf,smb_vwv2,1);
-
- /* register the name and uid as being validated, so further connections
- to a uid can get through without a password, on the same VC */
-
- sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name);
-
- if (sess_vuid == -1) {
- return(ERROR(ERRDOS,ERRnoaccess));
- }
-
-
- SSVAL(outbuf,smb_uid,sess_vuid);
- SSVAL(inbuf,smb_uid,sess_vuid);
-
- if (!done_sesssetup)
- max_send = MIN(max_send,smb_bufsize);
-
- DEBUG(6,("Client requested max send size of %d\n", max_send));
-
- done_sesssetup = True;
-
- END_PROFILE(SMBsesssetupX);
- return chain_reply(inbuf,outbuf,length,bufsize);
-}
-
/****************************************************************************
reply to a chkpth
****************************************************************************/
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBchkpth);
- srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
ok = S_ISDIR(sbuf.st_mode);
}
- if (!ok)
- {
+ if (!ok) {
/* We special case this - as when a Windows machine
is parsing a path is steps through the components
one at a time - if a component fails it expects
ERRbadpath, not ERRbadfile.
*/
- if(errno == ENOENT)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
-
-#if 0
- /* Ugly - NT specific hack - maybe not needed ? (JRA) */
- if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
- (get_remote_arch() == RA_WINNT))
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbaddirectory;
+ if(errno == ENOENT) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
-#endif
return(UNIXERROR(ERRDOS,ERRbadpath));
}
START_PROFILE(SMBgetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
if (!ok)
{
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
-
+ set_bad_path_error(errno, bad_path);
END_PROFILE(SMBgetatr);
return(UNIXERROR(ERRDOS,ERRbadfile));
}
put_dos_date3(outbuf,smb_vwv1,mtime);
SIVAL(outbuf,smb_vwv3,(uint32)size);
- if (Protocol >= PROTOCOL_NT1) {
- SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
- }
+ if (Protocol >= PROTOCOL_NT1)
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
START_PROFILE(SMBsetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
unix_convert(fname,conn,0,&bad_path,&sbuf);
mode = SVAL(inbuf,smb_vwv0);
if (VALID_STAT_OF_DIR(sbuf))
mode |= aDIR;
+ else
+ mode &= ~aDIR;
+
if (check_name(fname,conn))
ok = (file_chmod(conn,fname,mode,NULL) == 0);
if (ok)
if (!ok)
{
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
-
+ set_bad_path_error(errno, bad_path);
END_PROFILE(SMBsetatr);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
****************************************************************************/
int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = 0;
- SMB_BIG_UINT dfree,dsize,bsize;
- START_PROFILE(SMBdskattr);
-
- conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
-
- outsize = set_message(outbuf,5,0,True);
+ int outsize = 0;
+ SMB_BIG_UINT dfree,dsize,bsize;
+ START_PROFILE(SMBdskattr);
+
+ conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
- SSVAL(outbuf,smb_vwv0,dsize);
- SSVAL(outbuf,smb_vwv1,bsize/512);
- SSVAL(outbuf,smb_vwv2,512);
- SSVAL(outbuf,smb_vwv3,dfree);
+ outsize = set_message(outbuf,5,0,True);
+
+ if (Protocol <= PROTOCOL_LANMAN2) {
+ double total_space, free_space;
+ /* we need to scale this to a number that DOS6 can handle. We
+ use floating point so we can handle large drives on systems
+ that don't have 64 bit integers
+
+ we end up displaying a maximum of 2G to DOS systems
+ */
+ total_space = dsize * (double)bsize;
+ free_space = dfree * (double)bsize;
+
+ dsize = (total_space+63*512) / (64*512);
+ dfree = (free_space+63*512) / (64*512);
+
+ if (dsize > 0xFFFF) dsize = 0xFFFF;
+ if (dfree > 0xFFFF) dfree = 0xFFFF;
+
+ SSVAL(outbuf,smb_vwv0,dsize);
+ SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
+ SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
+ SSVAL(outbuf,smb_vwv3,dfree);
+ } else {
+ SSVAL(outbuf,smb_vwv0,dsize);
+ SSVAL(outbuf,smb_vwv1,bsize/512);
+ SSVAL(outbuf,smb_vwv2,512);
+ SSVAL(outbuf,smb_vwv3,dfree);
+ }
- DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
+ DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
- END_PROFILE(SMBdskattr);
- return(outsize);
+ END_PROFILE(SMBdskattr);
+ return(outsize);
}
maxentries = SVAL(inbuf,smb_vwv0);
dirtype = SVAL(inbuf,smb_vwv1);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
p++;
status_len = SVAL(p, 0);
p += 2;
if (strlen(directory) == 0)
pstrcpy(directory,"./");
memset((char *)status,'\0',21);
- CVAL(status,0) = dirtype;
+ SCVAL(status,0,dirtype);
}
else
{
{
if(dptr_num == -2)
{
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- END_PROFILE(SMBsearch);
+ set_bad_path_error(errno, bad_path);
+ END_PROFILE(SMBsearch);
return (UNIXERROR(ERRDOS,ERRnofids));
}
END_PROFILE(SMBsearch);
- return(ERROR(ERRDOS,ERRnofids));
+ return ERROR_DOS(ERRDOS,ERRnofids);
}
dptr_set_wcard(dptr_num, strdup(mask));
}
if (numentries == 0 || !ok)
{
- CVAL(outbuf,smb_rcls) = ERRDOS;
+ SCVAL(outbuf,smb_rcls,ERRDOS);
SSVAL(outbuf,smb_err,ERRnofiles);
dptr_close(&dptr_num);
}
if(ok && expect_close && numentries == 0 && status_len == 0)
{
- CVAL(outbuf,smb_rcls) = ERRDOS;
+ SCVAL(outbuf,smb_rcls,ERRDOS);
SSVAL(outbuf,smb_err,ERRnofiles);
/* Also close the dptr - we know it's gone */
dptr_close(&dptr_num);
SSVAL(outbuf,smb_vwv0,numentries);
SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
- CVAL(smb_buf(outbuf),0) = 5;
+ SCVAL(smb_buf(outbuf),0,5);
SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
- if (Protocol >= PROTOCOL_NT1) {
- SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
- }
+ if (Protocol >= PROTOCOL_NT1)
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
outsize += DIR_STRUCT_SIZE*numentries;
smb_setlen(outbuf,outsize - 4);
outsize = set_message(outbuf,1,0,True);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
p++;
status_len = SVAL(p,0);
p += 2;
if (status_len == 0) {
END_PROFILE(SMBfclose);
- return(ERROR(ERRSRV,ERRsrverror));
+ return ERROR_DOS(ERRSRV,ERRsrverror);
}
memcpy(status,p,21);
share_mode = SVAL(inbuf,smb_vwv0);
- srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
if (!fsp)
{
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ set_bad_path_error(errno, bad_path);
END_PROFILE(SMBopen);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
DEBUG(3,("attempt to open a directory %s\n",fname));
close_file(fsp,False);
END_PROFILE(SMBopen);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
outsize = set_message(outbuf,7,0,True);
SSVAL(outbuf,smb_vwv6,rmode);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
END_PROFILE(SMBopen);
return(outsize);
}
return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
} else {
END_PROFILE(SMBopenX);
- return (ERROR(ERRSRV,ERRaccess));
+ return ERROR_DOS(ERRSRV,ERRaccess);
}
}
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
if (!fsp)
{
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ set_bad_path_error(errno, bad_path);
END_PROFILE(SMBopenX);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
if (fmode & aDIR) {
close_file(fsp,False);
END_PROFILE(SMBopenX);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
/* If the caller set the extended oplock request bit
*/
if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
set_message(outbuf,15,0,True);
com = SVAL(inbuf,smb_com);
createmode = SVAL(inbuf,smb_vwv0);
- srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
if (!fsp)
{
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ set_bad_path_error(errno, bad_path);
END_PROFILE(SMBcreate);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
SSVAL(outbuf,smb_vwv0,fsp->fnum);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
DEBUG( 2, ( "new file %s\n", fname ) );
DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
int tmpfd;
SMB_STRUCT_STAT sbuf;
- char *p;
+ char *p, *s;
START_PROFILE(SMBctemp);
createmode = SVAL(inbuf,smb_vwv0);
- srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
- pstrcat(fname,"/TMXXXXXX");
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
+ pstrcat(fname,"\\TMXXXXXX");
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
/* close fd from smb_mkstemp() */
close(tmpfd);
- if (!fsp)
- {
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ if (!fsp) {
+ set_bad_path_error(errno, bad_path);
END_PROFILE(SMBctemp);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
- CVAL(smb_buf(outbuf),0) = 4;
- p = smb_buf(outbuf) + 1;
- p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
- set_message_end(outbuf, p);
+
+ /* the returned filename is relative to the directory */
+ s = strrchr_m(fname, '/');
+ if (!s) {
+ s = fname;
+ } else {
+ s++;
+ }
+
+ p = smb_buf(outbuf);
+ SSVALS(p, 0, -1); /* what is this? not in spec */
+ SSVAL(p, 2, strlen(s));
+ p += 4;
+ p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
+ outsize = set_message_end(outbuf, p);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
- if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
DEBUG( 2, ( "created temp file %s\n", fname ) );
DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
return(outsize);
}
-
/*******************************************************************
-check if a user is allowed to delete a file
+ Check if a user is allowed to rename a file.
********************************************************************/
-static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
-{
- SMB_STRUCT_STAT sbuf;
- int fmode;
-
- if (!CAN_WRITE(conn)) return(False);
-
- if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
- fmode = dos_mode(conn,fname,&sbuf);
- if (fmode & aDIR) return(False);
- if (!lp_delete_readonly(SNUM(conn))) {
- if (fmode & aRONLY) return(False);
- }
- if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
- return(False);
- if (!check_file_sharing(conn,fname,False)) return(False);
- return(True);
-}
-
-/****************************************************************************
- The guts of the unlink command, split out so it may be called by the NT SMB
- code.
-****************************************************************************/
-int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
- int dirtype, char *name)
+static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
{
- pstring directory;
- pstring mask;
- char *p;
- int count=0;
- int error = ERRnoaccess;
- BOOL has_wild;
- BOOL exists=False;
- BOOL bad_path = False;
- BOOL rc = True;
- SMB_STRUCT_STAT sbuf;
-
- *directory = *mask = 0;
+ int smb_action;
+ int access_mode;
+ files_struct *fsp;
- rc = unix_convert(name,conn,0,&bad_path,&sbuf);
+ if (!CAN_WRITE(conn))
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
+
+ if (S_ISDIR(pst->st_mode))
+ return NT_STATUS_OK;
- p = strrchr_m(name,'/');
- if (!p) {
- pstrcpy(directory,"./");
- pstrcpy(mask,name);
- } else {
- *p = 0;
- pstrcpy(directory,name);
- pstrcpy(mask,p+1);
- }
+ /* We need a better way to return NT status codes from open... */
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
- /*
- * We should only check the mangled cache
- * here if unix_convert failed. This means
- * that the path in 'mask' doesn't exist
- * on the file system and so we need to look
- * for a possible mangle. This patch from
- * Tine Smukavec <valentin.smukavec@hermes.si>.
- */
+ fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
- if (!rc && is_mangled(mask))
- check_mangled_cache( mask );
+ if (!fsp) {
+ NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
+ if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+ ret = NT_STATUS_SHARING_VIOLATION;
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
+ return ret;
+ }
+ close_file(fsp,False);
+ return NT_STATUS_OK;
+}
- has_wild = ms_has_wild(mask);
+/*******************************************************************
+ Check if a user is allowed to delete a file.
+********************************************************************/
- if (!has_wild) {
- pstrcat(directory,"/");
- pstrcat(directory,mask);
- if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
- count++;
- if (!count)
- exists = vfs_file_exist(conn,directory,&sbuf);
- } else {
- void *dirptr = NULL;
- char *dname;
+static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
+{
+ SMB_STRUCT_STAT sbuf;
+ int fmode;
+ int smb_action;
+ int access_mode;
+ files_struct *fsp;
- if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ if (!CAN_WRITE(conn))
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
- /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
- the pattern matches against the long name, otherwise the short name
- We don't implement this yet XXXX
- */
+ if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- if (dirptr)
- {
- error = ERRbadfile;
+ fmode = dos_mode(conn,fname,&sbuf);
+ if (fmode & aDIR)
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ if (!lp_delete_readonly(SNUM(conn))) {
+ if (fmode & aRONLY)
+ return NT_STATUS_CANNOT_DELETE;
+ }
+ if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
+ return NT_STATUS_CANNOT_DELETE;
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
+ /* We need a better way to return NT status codes from open... */
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
- while ((dname = ReadDirName(dirptr)))
- {
- pstring fname;
- pstrcpy(fname,dname);
-
- if(!mask_match(fname, mask, case_sensitive)) continue;
+ fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
- error = ERRnoaccess;
- slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- if (!can_delete(fname,conn,dirtype)) continue;
- if (!vfs_unlink(conn,fname)) count++;
- DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
- }
- CloseDir(dirptr);
- }
- }
-
- if (count == 0) {
- if (exists)
- return(ERROR(ERRDOS,error));
- else {
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- return(UNIXERROR(ERRDOS,error));
- }
- }
-
- return 0;
+ if (!fsp) {
+ NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
+ if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+ ret = NT_STATUS_SHARING_VIOLATION;
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
+ return ret;
+ }
+ close_file(fsp,False);
+ return NT_STATUS_OK;
}
/****************************************************************************
- Reply to a unlink
+ The guts of the unlink command, split out so it may be called by the NT SMB
+ code.
****************************************************************************/
-int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
{
- int outsize = 0;
- pstring name;
- int dirtype;
- START_PROFILE(SMBunlink);
-
- dirtype = SVAL(inbuf,smb_vwv0);
-
- srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
+ pstring directory;
+ pstring mask;
+ char *p;
+ int count=0;
+ NTSTATUS error = NT_STATUS_OK;
+ BOOL has_wild;
+ BOOL bad_path = False;
+ BOOL rc = True;
+ SMB_STRUCT_STAT sbuf;
+
+ *directory = *mask = 0;
+
+ rc = unix_convert(name,conn,0,&bad_path,&sbuf);
+
+ p = strrchr_m(name,'/');
+ if (!p) {
+ pstrcpy(directory,".");
+ pstrcpy(mask,name);
+ } else {
+ *p = 0;
+ pstrcpy(directory,name);
+ pstrcpy(mask,p+1);
+ }
+
+ /*
+ * We should only check the mangled cache
+ * here if unix_convert failed. This means
+ * that the path in 'mask' doesn't exist
+ * on the file system and so we need to look
+ * for a possible mangle. This patch from
+ * Tine Smukavec <valentin.smukavec@hermes.si>.
+ */
+
+ if (!rc && mangle_is_mangled(mask))
+ mangle_check_cache( mask );
+
+ has_wild = ms_has_wild(mask);
+
+ if (!has_wild) {
+ pstrcat(directory,"/");
+ pstrcat(directory,mask);
+ error = can_delete(directory,conn,dirtype);
+ if (!NT_STATUS_IS_OK(error)) return error;
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+ if (vfs_unlink(conn,directory) == 0) {
+ count++;
+ }
+ } else {
+ void *dirptr = NULL;
+ char *dname;
+
+ if (check_name(directory,conn))
+ dirptr = OpenDir(conn, directory, True);
+
+ /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
+ the pattern matches against the long name, otherwise the short name
+ We don't implement this yet XXXX
+ */
+
+ if (dirptr) {
+ error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ if (strequal(mask,"????????.???"))
+ pstrcpy(mask,"*");
- DEBUG(3,("reply_unlink : %s\n",name));
+ while ((dname = ReadDirName(dirptr))) {
+ pstring fname;
+ pstrcpy(fname,dname);
+
+ if(!mask_match(fname, mask, case_sensitive)) continue;
+
+ slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+ error = can_delete(fname,conn,dirtype);
+ if (!NT_STATUS_IS_OK(error)) continue;
+ if (vfs_unlink(conn,fname) == 0) count++;
+ DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
+ }
+ CloseDir(dirptr);
+ }
+ }
+
+ if (count == 0 && NT_STATUS_IS_OK(error)) {
+ error = map_nt_error_from_unix(errno);
+ }
- outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
- if(outsize == 0) {
+ return error;
+}
- /*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
+/****************************************************************************
+ Reply to a unlink
+****************************************************************************/
- process_pending_change_notify_queue((time_t)0);
+int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
+ int dum_buffsize)
+{
+ int outsize = 0;
+ pstring name;
+ int dirtype;
+ NTSTATUS status;
+ START_PROFILE(SMBunlink);
+
+ dirtype = SVAL(inbuf,smb_vwv0);
+
+ srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
+
+ RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+
+ DEBUG(3,("reply_unlink : %s\n",name));
+
+ status = unlink_internals(conn, dirtype, name);
+ if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
- outsize = set_message(outbuf,0,0,True);
- }
+ /*
+ * Win2k needs a changenotify request response before it will
+ * update after a rename..
+ */
+ process_pending_change_notify_queue((time_t)0);
+
+ outsize = set_message(outbuf,0,0,True);
- END_PROFILE(SMBunlink);
- return(outsize);
+ END_PROFILE(SMBunlink);
+ return outsize;
}
+/****************************************************************************
+ Fail for readbraw.
+****************************************************************************/
+
+void fail_readraw(void)
+{
+ pstring errstr;
+ slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
+ strerror(errno) );
+ exit_server(errstr);
+}
/****************************************************************************
- reply to a readbraw (core+ protocol)
+ Reply to a readbraw (core+ protocol).
****************************************************************************/
int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
{
- size_t maxcount,mincount;
- size_t nread = 0;
- SMB_OFF_T startpos;
- char *header = outbuf;
- ssize_t ret=0;
- files_struct *fsp;
- START_PROFILE(SMBreadbraw);
+ ssize_t maxcount,mincount;
+ size_t nread = 0;
+ SMB_OFF_T startpos;
+ char *header = outbuf;
+ ssize_t ret=0;
+ files_struct *fsp;
+ START_PROFILE(SMBreadbraw);
- /*
- * Special check if an oplock break has been issued
- * and the readraw request croses on the wire, we must
- * return a zero length response here.
- */
+ /*
+ * Special check if an oplock break has been issued
+ * and the readraw request croses on the wire, we must
+ * return a zero length response here.
+ */
- if(global_oplock_break)
- {
- _smb_setlen(header,0);
- transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
- DEBUG(5,("readbraw - oplock break finished\n"));
- END_PROFILE(SMBreadbraw);
- return -1;
- }
+ if(global_oplock_break) {
+ _smb_setlen(header,0);
+ if (write_data(smbd_server_fd(),header,4) != 4)
+ fail_readraw();
+ DEBUG(5,("readbraw - oplock break finished\n"));
+ END_PROFILE(SMBreadbraw);
+ return -1;
+ }
- fsp = file_fsp(inbuf,smb_vwv0);
-
- if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
- /*
- * fsp could be NULL here so use the value from the packet. JRA.
- */
- DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
- _smb_setlen(header,0);
- transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
- END_PROFILE(SMBreadbraw);
- return(-1);
- }
+ fsp = file_fsp(inbuf,smb_vwv0);
- CHECK_FSP(fsp,conn);
+ if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
+ /*
+ * fsp could be NULL here so use the value from the packet. JRA.
+ */
+ DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
+ _smb_setlen(header,0);
+ if (write_data(smbd_server_fd(),header,4) != 4)
+ fail_readraw();
+ END_PROFILE(SMBreadbraw);
+ return(-1);
+ }
- flush_write_cache(fsp, READRAW_FLUSH);
+ CHECK_FSP(fsp,conn);
- startpos = IVAL(inbuf,smb_vwv1);
- if(CVAL(inbuf,smb_wct) == 10) {
- /*
- * This is a large offset (64 bit) read.
- */
+ flush_write_cache(fsp, READRAW_FLUSH);
+
+ startpos = IVAL(inbuf,smb_vwv1);
+ if(CVAL(inbuf,smb_wct) == 10) {
+ /*
+ * This is a large offset (64 bit) read.
+ */
#ifdef LARGE_SMB_OFF_T
- startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
+ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
#else /* !LARGE_SMB_OFF_T */
- /*
- * Ensure we haven't been sent a >32 bit offset.
- */
+ /*
+ * Ensure we haven't been sent a >32 bit offset.
+ */
- if(IVAL(inbuf,smb_vwv8) != 0) {
- DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
+ if(IVAL(inbuf,smb_vwv8) != 0) {
+ DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
- _smb_setlen(header,0);
- transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
- END_PROFILE(SMBreadbraw);
- return(-1);
- }
+ _smb_setlen(header,0);
+ if (write_data(smbd_server_fd(),header,4) != 4)
+ fail_readraw();
+ END_PROFILE(SMBreadbraw);
+ return(-1);
+ }
#endif /* LARGE_SMB_OFF_T */
- if(startpos < 0) {
- DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
- (double)startpos ));
- _smb_setlen(header,0);
- transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
- END_PROFILE(SMBreadbraw);
- return(-1);
- }
- }
- maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
- mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
+ if(startpos < 0) {
+ DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
+ _smb_setlen(header,0);
+ if (write_data(smbd_server_fd(),header,4) != 4)
+ fail_readraw();
+ END_PROFILE(SMBreadbraw);
+ return(-1);
+ }
+ }
+ maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
+ mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
- /* ensure we don't overrun the packet size */
- maxcount = MIN(65535,maxcount);
- maxcount = MAX(mincount,maxcount);
+ /* ensure we don't overrun the packet size */
+ maxcount = MIN(65535,maxcount);
+ maxcount = MAX(mincount,maxcount);
- if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
- {
- SMB_OFF_T size = fsp->size;
- SMB_OFF_T sizeneeded = startpos + maxcount;
-
- if (size < sizeneeded)
- {
- SMB_STRUCT_STAT st;
- if (vfs_fstat(fsp,fsp->fd,&st) == 0)
- size = st.st_size;
- if (!fsp->can_write)
- fsp->size = size;
- }
+ if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ SMB_OFF_T size = fsp->size;
+ SMB_OFF_T sizeneeded = startpos + maxcount;
+
+ if (size < sizeneeded) {
+ SMB_STRUCT_STAT st;
+ if (vfs_fstat(fsp,fsp->fd,&st) == 0)
+ size = st.st_size;
+ if (!fsp->can_write)
+ fsp->size = size;
+ }
- nread = MIN(maxcount,(size - startpos));
- }
+ if (startpos >= size)
+ nread = 0;
+ else
+ nread = MIN(maxcount,(size - startpos));
+ }
- if (nread < mincount)
- nread = 0;
+ if (nread < mincount)
+ nread = 0;
- DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
- fsp->fnum, (double)startpos,
- (int)maxcount, (int)mincount, (int)nread ) );
+ DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
+ (int)maxcount, (int)mincount, (int)nread ) );
-#if UNSAFE_READRAW
- {
- BOOL seek_fail = False;
- int predict=0;
- _smb_setlen(header,nread);
-
- if ((nread-predict) > 0) {
- if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
- DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
- ret = 0;
- seek_fail = True;
- }
- }
-
- if(!seek_fail)
- ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
- (SMB_OFF_T)(nread-predict),header,4+predict,
- startpos+predict);
- }
-
- if (ret != nread+4)
- DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
- fsp->fsp_name,startpos,nread,ret));
-
-#else /* UNSAFE_READRAW */
- ret = read_file(fsp,header+4,startpos,nread);
- if (ret < mincount) ret = 0;
+ if (nread > 0) {
+ ret = read_file(fsp,header+4,startpos,nread);
+ if (ret < mincount)
+ ret = 0;
+ }
- _smb_setlen(header,ret);
- transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
-#endif /* UNSAFE_READRAW */
+ _smb_setlen(header,ret);
+ if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
+ fail_readraw();
- DEBUG(5,("readbraw finished\n"));
- END_PROFILE(SMBreadbraw);
- return -1;
+ DEBUG(5,("readbraw finished\n"));
+ END_PROFILE(SMBreadbraw);
+ return -1;
}
-
/****************************************************************************
reply to a lockread (core+ protocol)
****************************************************************************/
int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
{
- ssize_t nread = -1;
- char *data;
- int outsize = 0;
- SMB_OFF_T startpos;
- size_t numtoread;
- int eclass;
- uint32 ecode;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBlockread);
+ ssize_t nread = -1;
+ char *data;
+ int outsize = 0;
+ SMB_OFF_T startpos;
+ size_t numtoread;
+ NTSTATUS status;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBlockread);
- CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
- CHECK_ERROR(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_READ(fsp);
- release_level_2_oplocks_on_change(fsp);
+ release_level_2_oplocks_on_change(fsp);
- numtoread = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv2);
+ numtoread = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
- outsize = set_message(outbuf,5,3,True);
- numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
- data = smb_buf(outbuf) + 3;
-
- /*
- * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
- * protocol request that predates the read/write lock concept.
- * Thus instead of asking for a read lock here we need to ask
- * for a write lock. JRA.
- */
+ outsize = set_message(outbuf,5,3,True);
+ numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
+ data = smb_buf(outbuf) + 3;
+
+ /*
+ * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
+ * protocol request that predates the read/write lock concept.
+ * Thus instead of asking for a read lock here we need to ask
+ * for a write lock. JRA.
+ */
+
+ status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
+ (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
- if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
- if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length, -1, 0))
+ if (NT_STATUS_V(status)) {
+ if (lp_blocking_locks(SNUM(conn))) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(inbuf, length, -1, 0))
+ END_PROFILE(SMBlockread);
+ return -1;
+ }
END_PROFILE(SMBlockread);
- return -1;
- }
- END_PROFILE(SMBlockread);
- return (ERROR(eclass,ecode));
- }
-
- nread = read_file(fsp,data,startpos,numtoread);
-
- if (nread < 0) {
- END_PROFILE(SMBlockread);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ return ERROR_NT(status);
+ }
- outsize += nread;
- SSVAL(outbuf,smb_vwv0,nread);
- SSVAL(outbuf,smb_vwv5,nread+3);
- SSVAL(smb_buf(outbuf),1,nread);
+ nread = read_file(fsp,data,startpos,numtoread);
- DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
- fsp->fnum, (int)numtoread, (int)nread ) );
+ if (nread < 0) {
+ END_PROFILE(SMBlockread);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ outsize += nread;
+ SSVAL(outbuf,smb_vwv0,nread);
+ SSVAL(outbuf,smb_vwv5,nread+3);
+ SSVAL(smb_buf(outbuf),1,nread);
+
+ DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
+ fsp->fnum, (int)numtoread, (int)nread));
- END_PROFILE(SMBlockread);
- return(outsize);
+ END_PROFILE(SMBlockread);
+ return(outsize);
}
CHECK_FSP(fsp,conn);
CHECK_READ(fsp);
- CHECK_ERROR(fsp);
numtoread = SVAL(inbuf,smb_vwv1);
startpos = IVAL(inbuf,smb_vwv2);
-
+
+
outsize = set_message(outbuf,5,3,True);
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
data = smb_buf(outbuf) + 3;
if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
END_PROFILE(SMBread);
- return(ERROR(ERRDOS,ERRlock));
+ return ERROR_DOS(ERRDOS,ERRlock);
}
if (numtoread > 0)
nread = read_file(fsp,data,startpos,numtoread);
-
+
if (nread < 0) {
END_PROFILE(SMBread);
return(UNIXERROR(ERRDOS,ERRnoaccess));
outsize += nread;
SSVAL(outbuf,smb_vwv0,nread);
SSVAL(outbuf,smb_vwv5,nread+3);
- CVAL(smb_buf(outbuf),0) = 1;
+ SCVAL(smb_buf(outbuf),0,1);
SSVAL(smb_buf(outbuf),1,nread);
DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
CHECK_FSP(fsp,conn);
CHECK_READ(fsp);
- CHECK_ERROR(fsp);
set_message(outbuf,12,0,True);
data = smb_buf(outbuf);
DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
END_PROFILE(SMBreadX);
- return(ERROR(ERRDOS,ERRbadaccess));
+ return ERROR_DOS(ERRDOS,ERRbadaccess);
}
#endif /* LARGE_SMB_OFF_T */
if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
END_PROFILE(SMBreadX);
- return(ERROR(ERRDOS,ERRlock));
+ return ERROR_DOS(ERRDOS,ERRlock);
}
nread = read_file(fsp,data,startpos,smb_maxcnt);
-
+
if (nread < 0) {
END_PROFILE(SMBreadX);
return(UNIXERROR(ERRDOS,ERRnoaccess));
int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- ssize_t nwritten=0;
- ssize_t total_written=0;
- size_t numtowrite=0;
- size_t tcount;
- SMB_OFF_T startpos;
- char *data=NULL;
- BOOL write_through;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- int outsize = 0;
- START_PROFILE(SMBwritebraw);
+ ssize_t nwritten=0;
+ ssize_t total_written=0;
+ size_t numtowrite=0;
+ size_t tcount;
+ SMB_OFF_T startpos;
+ char *data=NULL;
+ BOOL write_through;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ int outsize = 0;
+ START_PROFILE(SMBwritebraw);
- CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
- tcount = IVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv3);
- write_through = BITSETW(inbuf+smb_vwv7,0);
-
- /* We have to deal with slightly different formats depending
- on whether we are using the core+ or lanman1.0 protocol */
- if(Protocol <= PROTOCOL_COREPLUS) {
- numtowrite = SVAL(smb_buf(inbuf),-2);
- data = smb_buf(inbuf);
- } else {
- numtowrite = SVAL(inbuf,smb_vwv10);
- data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
- }
+ tcount = IVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv3);
+ write_through = BITSETW(inbuf+smb_vwv7,0);
- /* force the error type */
- CVAL(inbuf,smb_com) = SMBwritec;
- CVAL(outbuf,smb_com) = SMBwritec;
+ /* We have to deal with slightly different formats depending
+ on whether we are using the core+ or lanman1.0 protocol */
- if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
- END_PROFILE(SMBwritebraw);
- return(ERROR(ERRDOS,ERRlock));
- }
+ if(Protocol <= PROTOCOL_COREPLUS) {
+ numtowrite = SVAL(smb_buf(inbuf),-2);
+ data = smb_buf(inbuf);
+ } else {
+ numtowrite = SVAL(inbuf,smb_vwv10);
+ data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
+ }
- if (numtowrite>0)
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ /* force the error type */
+ SCVAL(inbuf,smb_com,SMBwritec);
+ SCVAL(outbuf,smb_com,SMBwritec);
+
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
+ END_PROFILE(SMBwritebraw);
+ return(ERROR_DOS(ERRDOS,ERRlock));
+ }
+
+ if (numtowrite>0)
+ nwritten = write_file(fsp,data,startpos,numtowrite);
- DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
- fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
+ DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
+ fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
- if (nwritten < numtowrite) {
- END_PROFILE(SMBwritebraw);
- return(UNIXERROR(ERRHRD,ERRdiskfull));
- }
+ if (nwritten < numtowrite) {
+ END_PROFILE(SMBwritebraw);
+ return(UNIXERROR(ERRHRD,ERRdiskfull));
+ }
- total_written = nwritten;
+ total_written = nwritten;
- /* Return a message to the redirector to tell it
- to send more bytes */
- CVAL(outbuf,smb_com) = SMBwritebraw;
- SSVALS(outbuf,smb_vwv0,-1);
- outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_writebraw: send_smb failed.\n");
+ /* Return a message to the redirector to tell it to send more bytes */
+ SCVAL(outbuf,smb_com,SMBwritebraw);
+ SSVALS(outbuf,smb_vwv0,-1);
+ outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("reply_writebraw: send_smb failed.");
- /* Now read the raw data into the buffer and write it */
- if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
- exit_server("secondary writebraw failed");
- }
+ /* Now read the raw data into the buffer and write it */
+ if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
+ exit_server("secondary writebraw failed");
+ }
- /* Even though this is not an smb message, smb_len
- returns the generic length of an smb message */
- numtowrite = smb_len(inbuf);
+ /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
+ numtowrite = smb_len(inbuf);
- if (tcount > nwritten+numtowrite) {
- DEBUG(3,("Client overestimated the write %d %d %d\n",
- (int)tcount,(int)nwritten,(int)numtowrite));
- }
+ /* Set up outbuf to return the correct return */
+ outsize = set_message(outbuf,1,0,True);
+ SCVAL(outbuf,smb_com,SMBwritec);
+ SSVAL(outbuf,smb_vwv0,total_written);
- nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
- (SMB_OFF_T)numtowrite,NULL,0,
- startpos+nwritten);
- total_written += nwritten;
-
- /* Set up outbuf to return the correct return */
- outsize = set_message(outbuf,1,0,True);
- CVAL(outbuf,smb_com) = SMBwritec;
- SSVAL(outbuf,smb_vwv0,total_written);
+ if (numtowrite != 0) {
- if (nwritten < (ssize_t)numtowrite) {
- CVAL(outbuf,smb_rcls) = ERRHRD;
- SSVAL(outbuf,smb_err,ERRdiskfull);
- }
+ if (numtowrite > BUFFER_SIZE) {
+ DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
+ (unsigned int)numtowrite ));
+ exit_server("secondary writebraw failed");
+ }
- if ((lp_syncalways(SNUM(conn)) || write_through) &&
- lp_strict_sync(SNUM(conn)))
- sync_file(conn,fsp);
+ if (tcount > nwritten+numtowrite) {
+ DEBUG(3,("Client overestimated the write %d %d %d\n",
+ (int)tcount,(int)nwritten,(int)numtowrite));
+ }
- DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
- fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
+ if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
+ DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
+ strerror(errno) ));
+ exit_server("secondary writebraw failed");
+ }
- /* we won't return a status if write through is not selected - this
- follows what WfWg does */
- END_PROFILE(SMBwritebraw);
- if (!write_through && total_written==tcount) {
- /*
- * Fix for "rabbit pellet" mode, trigger an early TCP ack by
- * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
- */
- if (!send_keepalive(smbd_server_fd()))
- exit_server("reply_writebraw: send of keepalive failed");
- return(-1);
- }
+ nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
- return(outsize);
+ if (nwritten < (ssize_t)numtowrite) {
+ SCVAL(outbuf,smb_rcls,ERRHRD);
+ SSVAL(outbuf,smb_err,ERRdiskfull);
+ }
+
+ if (nwritten > 0)
+ total_written += nwritten;
+ }
+
+ if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
+ sync_file(conn,fsp);
+
+ DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
+ fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
+
+ /* we won't return a status if write through is not selected - this follows what WfWg does */
+ END_PROFILE(SMBwritebraw);
+ if (!write_through && total_written==tcount) {
+
+#if RABBIT_PELLET_FIX
+ /*
+ * Fix for "rabbit pellet" mode, trigger an early TCP ack by
+ * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
+ */
+ if (!send_keepalive(smbd_server_fd()))
+ exit_server("reply_writebraw: send of keepalive failed");
+#endif
+ return(-1);
+ }
+
+ return(outsize);
}
/****************************************************************************
reply to a writeunlock (core+)
****************************************************************************/
-int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
+ int size, int dum_buffsize)
{
- ssize_t nwritten = -1;
- size_t numtowrite;
- SMB_OFF_T startpos;
- char *data;
- int eclass;
- uint32 ecode;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- int outsize = 0;
- START_PROFILE(SMBwriteunlock);
-
- CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
-
- numtowrite = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv2);
- data = smb_buf(inbuf) + 3;
-
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
- END_PROFILE(SMBwriteunlock);
- return(ERROR(ERRDOS,ERRlock));
- }
+ ssize_t nwritten = -1;
+ size_t numtowrite;
+ SMB_OFF_T startpos;
+ char *data;
+ NTSTATUS status;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ int outsize = 0;
+ START_PROFILE(SMBwriteunlock);
+
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
- /* The special X/Open SMB protocol handling of
- zero length writes is *NOT* done for
- this call */
- if(numtowrite == 0)
- nwritten = 0;
- else
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ numtowrite = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
+ data = smb_buf(inbuf) + 3;
- if (lp_syncalways(SNUM(conn)))
- sync_file(conn,fsp);
-
- if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
- END_PROFILE(SMBwriteunlock);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
- END_PROFILE(SMBwriteunlock);
- return(ERROR(eclass,ecode));
- }
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
+ WRITE_LOCK,False)) {
+ END_PROFILE(SMBwriteunlock);
+ return ERROR_DOS(ERRDOS,ERRlock);
+ }
- outsize = set_message(outbuf,1,0,True);
-
- SSVAL(outbuf,smb_vwv0,nwritten);
+ /* The special X/Open SMB protocol handling of
+ zero length writes is *NOT* done for
+ this call */
+ if(numtowrite == 0)
+ nwritten = 0;
+ else
+ nwritten = write_file(fsp,data,startpos,numtowrite);
- DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
- fsp->fnum, (int)numtowrite, (int)nwritten ) );
-
- END_PROFILE(SMBwriteunlock);
- return(outsize);
-}
-
-/****************************************************************************
- Return correct error for space allocation fail.
-****************************************************************************/
+ if (lp_syncalways(SNUM(conn)))
+ sync_file(conn,fsp);
-int allocate_space_error(char *inbuf,char *outbuf, int errno_val)
-{
- errno = errno_val;
- if (!(global_client_caps & CAP_STATUS32))
- return (UNIXERROR(ERRHRD,ERRdiskfull));
-
- /* Use more specific WNT/W2K error codes. */
-#ifdef EDQUOT
- if (errno_val == ENOSPC || errno_val == EDQUOT) {
-#else
- if (errno_val == ENOSPC) {
-#endif
- SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return(ERROR(0,NT_STATUS_DISK_FULL));
+ if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+ END_PROFILE(SMBwriteunlock);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- return (UNIXERROR(ERRHRD,ERRdiskfull));
+ status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
+ (SMB_BIG_UINT)startpos);
+ if (NT_STATUS_V(status)) {
+ END_PROFILE(SMBwriteunlock);
+ return ERROR_NT(status);
+ }
+
+ outsize = set_message(outbuf,1,0,True);
+
+ SSVAL(outbuf,smb_vwv0,nwritten);
+
+ DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
+ fsp->fnum, (int)numtowrite, (int)nwritten));
+
+ END_PROFILE(SMBwriteunlock);
+ return outsize;
}
+
/****************************************************************************
Reply to a write.
****************************************************************************/
int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
{
- size_t numtowrite;
- ssize_t nwritten = -1;
- SMB_OFF_T startpos;
- char *data;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- int outsize = 0;
- START_PROFILE(SMBwrite);
+ size_t numtowrite;
+ ssize_t nwritten = -1;
+ SMB_OFF_T startpos;
+ char *data;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ int outsize = 0;
+ START_PROFILE(SMBwrite);
- /* If it's an IPC, pass off the pipe handler. */
- if (IS_IPC(conn)) {
- END_PROFILE(SMBwrite);
- return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
- }
+ /* If it's an IPC, pass off the pipe handler. */
+ if (IS_IPC(conn)) {
+ END_PROFILE(SMBwrite);
+ return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
+ }
- CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
- numtowrite = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv2);
- data = smb_buf(inbuf) + 3;
+ numtowrite = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
+ data = smb_buf(inbuf) + 3;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
- END_PROFILE(SMBwrite);
- return(ERROR(ERRDOS,ERRlock));
- }
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
+ END_PROFILE(SMBwrite);
+ return ERROR_DOS(ERRDOS,ERRlock);
+ }
- /* X/Open SMB protocol says that if smb_vwv1 is
- zero then the file size should be extended or
- truncated to the size given in smb_vwv[2-3] */
- if(numtowrite == 0) {
- /* This is actually an allocate call, not set EOF. JRA */
- nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
- if (nwritten < 0) {
- int ret = allocate_space_error(inbuf, outbuf, errno);
- END_PROFILE(SMBwrite);
- return ret;
- }
- } else
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ /*
+ * X/Open SMB protocol says that if smb_vwv1 is
+ * zero then the file size should be extended or
+ * truncated to the size given in smb_vwv[2-3].
+ */
+
+ if(numtowrite == 0) {
+ /*
+ * This is actually an allocate call, and set EOF. JRA.
+ */
+ nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
+ if (nwritten < 0) {
+ END_PROFILE(SMBwrite);
+ return ERROR_NT(NT_STATUS_DISK_FULL);
+ }
+ nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
+ if (nwritten < 0) {
+ END_PROFILE(SMBwrite);
+ return ERROR_NT(NT_STATUS_DISK_FULL);
+ }
+ } else
+ nwritten = write_file(fsp,data,startpos,numtowrite);
- if (lp_syncalways(SNUM(conn)))
- sync_file(conn,fsp);
+ if (lp_syncalways(SNUM(conn)))
+ sync_file(conn,fsp);
- if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
- END_PROFILE(SMBwrite);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+ END_PROFILE(SMBwrite);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- outsize = set_message(outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
- SSVAL(outbuf,smb_vwv0,nwritten);
+ SSVAL(outbuf,smb_vwv0,nwritten);
- if (nwritten < (ssize_t)numtowrite) {
- CVAL(outbuf,smb_rcls) = ERRHRD;
- SSVAL(outbuf,smb_err,ERRdiskfull);
- }
+ if (nwritten < (ssize_t)numtowrite) {
+ SCVAL(outbuf,smb_rcls,ERRHRD);
+ SSVAL(outbuf,smb_err,ERRdiskfull);
+ }
- DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
- fsp->fnum, (int)numtowrite, (int)nwritten));
+ DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
- END_PROFILE(SMBwrite);
- return(outsize);
+ END_PROFILE(SMBwrite);
+ return(outsize);
}
CHECK_FSP(fsp,conn);
CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
/* Deal with possible LARGE_WRITEX */
if (large_writeX)
if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
END_PROFILE(SMBwriteX);
- return(ERROR(ERRDOS,ERRbadmem));
+ return ERROR_DOS(ERRDOS,ERRbadmem);
}
data = smb_base(inbuf) + smb_doff;
DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
END_PROFILE(SMBwriteX);
- return(ERROR(ERRDOS,ERRbadaccess));
+ return ERROR_DOS(ERRDOS,ERRbadaccess);
}
#endif /* LARGE_SMB_OFF_T */
if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
END_PROFILE(SMBwriteX);
- return(ERROR(ERRDOS,ERRlock));
+ return ERROR_DOS(ERRDOS,ERRlock);
}
/* X/Open SMB protocol says that, unlike SMBwrite
SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
if (nwritten < (ssize_t)numtowrite) {
- CVAL(outbuf,smb_rcls) = ERRHRD;
+ SCVAL(outbuf,smb_rcls,ERRHRD);
SSVAL(outbuf,smb_err,ERRdiskfull);
}
START_PROFILE(SMBlseek);
CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
flush_write_cache(fsp, SEEK_FLUSH);
START_PROFILE(SMBflush);
CHECK_FSP(fsp,conn);
- if (fsp) {
- CHECK_ERROR(fsp);
- }
if (!fsp) {
file_sync_all(conn);
if(!fsp || (fsp->conn != conn)) {
END_PROFILE(SMBclose);
- return(ERROR(ERRDOS,ERRbadfid));
+ return ERROR_DOS(ERRDOS,ERRbadfid);
}
- if(HAS_CACHED_ERROR(fsp)) {
- eclass = fsp->wbmpx_ptr->wr_errclass;
- err = fsp->wbmpx_ptr->wr_error;
- }
-
- if(fsp->is_directory || fsp->stat_open) {
+ if(fsp->is_directory) {
/*
- * Special case - close NT SMB directory or stat file
- * handle.
+ * Special case - close NT SMB directory handle.
*/
DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
close_file(fsp,True);
* Close ordinary file.
*/
int close_err;
+ pstring file_name;
- /*
- * If there was a modify time outstanding,
- * try and set it here.
- */
- if(fsp->pending_modtime)
- set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
-
- /*
- * Now take care of any time sent in the close.
- */
- mtime = make_unix_date3(inbuf+smb_vwv1);
-
- /* try and set the date */
- set_filetime(conn, fsp->fsp_name,mtime);
+ /* Save the name for time set in close. */
+ pstrcpy( file_name, fsp->fsp_name);
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
fsp->fd, fsp->fnum,
END_PROFILE(SMBclose);
return (UNIXERROR(ERRHRD,ERRgeneral));
}
+
+ /*
+ * Now take care of any time sent in the close.
+ */
+
+ mtime = make_unix_date3(inbuf+smb_vwv1);
+
+ /* try and set the date */
+ set_filetime(conn, file_name, mtime);
+
}
/* We have a cached error */
if(eclass || err) {
END_PROFILE(SMBclose);
- return(ERROR(eclass,err));
+ return ERROR_DOS(eclass,err);
}
END_PROFILE(SMBclose);
CHECK_FSP(fsp,conn);
CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL(inbuf,smb_vwv2);
if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
END_PROFILE(SMBwriteclose);
- return(ERROR(ERRDOS,ERRlock));
+ return ERROR_DOS(ERRDOS,ERRlock);
}
nwritten = write_file(fsp,data,startpos,numtowrite);
{
int outsize = set_message(outbuf,0,0,True);
SMB_BIG_UINT count,offset;
- int eclass;
- uint32 ecode;
+ NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBlock);
CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
release_level_2_oplocks_on_change(fsp);
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
fsp->fd, fsp->fnum, (double)offset, (double)count));
- if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
- if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length, -1, 0)) {
- END_PROFILE(SMBlock);
- return -1;
- }
- }
- END_PROFILE(SMBlock);
- return (ERROR(eclass,ecode));
+ status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
+ if (NT_STATUS_V(status)) {
+ if (lp_blocking_locks(SNUM(conn))) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(inbuf, length, -1, 0)) {
+ END_PROFILE(SMBlock);
+ return -1;
+ }
+ }
+ END_PROFILE(SMBlock);
+ return ERROR_NT(status);
}
END_PROFILE(SMBlock);
/****************************************************************************
reply to a unlock
****************************************************************************/
-int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
+ int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,True);
- SMB_BIG_UINT count,offset;
- int eclass;
- uint32 ecode;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBunlock);
-
- CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
-
- count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
- offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
+ int outsize = set_message(outbuf,0,0,True);
+ SMB_BIG_UINT count,offset;
+ NTSTATUS status;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBunlock);
- if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
- END_PROFILE(SMBunlock);
- return (ERROR(eclass,ecode));
- }
+ CHECK_FSP(fsp,conn);
+
+ count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
+ offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
+
+ status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
+ if (NT_STATUS_V(status)) {
+ END_PROFILE(SMBunlock);
+ return ERROR_NT(status);
+ }
- DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fd, fsp->fnum, (double)offset, (double)count ) );
-
- END_PROFILE(SMBunlock);
- return(outsize);
+ DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
+ fsp->fd, fsp->fnum, (double)offset, (double)count ) );
+
+ END_PROFILE(SMBunlock);
+ return(outsize);
}
if (!conn) {
DEBUG(4,("Invalid connection in tdis\n"));
END_PROFILE(SMBtdis);
- return(ERROR(ERRSRV,ERRinvnid));
+ return ERROR_DOS(ERRSRV,ERRinvnid);
}
conn->used = False;
smb_setlen(outbuf,outsize - 4);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_echo: send_smb failed.\n");
+ exit_server("reply_echo: send_smb failed.");
}
DEBUG(3,("echo %d times\n", smb_reverb));
if (!CAN_PRINT(conn)) {
END_PROFILE(SMBsplopen);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
/* Open for exclusive use, write only. */
- fsp = print_fsp_open(conn);
+ fsp = print_fsp_open(conn, NULL);
if (!fsp) {
END_PROFILE(SMBsplopen);
START_PROFILE(SMBsplclose);
CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
if (!CAN_PRINT(conn)) {
END_PROFILE(SMBsplclose);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
DEBUG(3,("printclose fd=%d fnum=%d\n",
get it right (tridge) */
if (!CAN_PRINT(conn)) {
END_PROFILE(SMBsplretq);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
SSVAL(outbuf,smb_vwv0,0);
SSVAL(outbuf,smb_vwv1,0);
- CVAL(smb_buf(outbuf),0) = 1;
+ SCVAL(smb_buf(outbuf),0,1);
SSVAL(smb_buf(outbuf),1,0);
DEBUG(3,("printqueue start_index=%d max_count=%d\n",
{
print_queue_struct *queue = NULL;
+ print_status_struct status;
char *p = smb_buf(outbuf) + 3;
- int count = print_queue_status(SNUM(conn), &queue,NULL);
+ int count = print_queue_status(SNUM(conn), &queue, &status);
int num_to_get = ABS(max_count);
int first = (max_count>0?start_index:start_index+max_count+1);
int i;
for (i=first;i<first+num_to_get;i++) {
put_dos_date2(p,0,queue[i].time);
- CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
+ SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
SSVAL(p,5, queue[i].job);
SIVAL(p,7,queue[i].size);
- CVAL(p,11) = 0;
- srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
+ SCVAL(p,11,0);
+ srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
p += 28;
}
outsize = set_message(outbuf,2,28*count+3,False);
SSVAL(outbuf,smb_vwv0,count);
SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
- CVAL(smb_buf(outbuf),0) = 1;
+ SCVAL(smb_buf(outbuf),0,1);
SSVAL(smb_buf(outbuf),1,28*count);
}
- if (queue) free(queue);
+ SAFE_FREE(queue);
DEBUG(3,("%d entries returned in queue\n",count));
}
if (!CAN_PRINT(conn)) {
END_PROFILE(SMBsplwr);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
CHECK_FSP(fsp,conn);
CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
numtowrite = SVAL(smb_buf(inbuf),1);
data = smb_buf(inbuf) + 3;
The guts of the mkdir command, split out so it may be called by the NT SMB
code.
****************************************************************************/
-int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
+NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
{
- BOOL bad_path = False;
- SMB_STRUCT_STAT sbuf;
- int ret= -1;
-
- unix_convert(directory,conn,0,&bad_path,&sbuf);
-
- if (check_name(directory, conn))
- ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
-
- if (ret < 0)
- {
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- return ret;
+ BOOL bad_path = False;
+ SMB_STRUCT_STAT sbuf;
+ int ret= -1;
+
+ unix_convert(directory,conn,0,&bad_path,&sbuf);
+
+ if (check_name(directory, conn))
+ ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
+
+ if (ret == -1) {
+ NTSTATUS nterr = set_bad_path_error(errno, bad_path);
+ if (!NT_STATUS_IS_OK(nterr))
+ return nterr;
+ return map_nt_error_from_unix(errno);
+ }
+
+ return NT_STATUS_OK;
}
/****************************************************************************
- reply to a mkdir
+ Reply to a mkdir.
****************************************************************************/
+
int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- pstring directory;
- int outsize;
- START_PROFILE(SMBmkdir);
+ pstring directory;
+ int outsize;
+ NTSTATUS status;
+ START_PROFILE(SMBmkdir);
- srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
+
+ status = mkdir_internal(conn, directory);
+ if (!NT_STATUS_IS_OK(status))
+ return ERROR_NT(status);
- outsize=mkdir_internal(conn, inbuf, outbuf, directory);
- if(outsize == 0)
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,True);
- DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
+ DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
- END_PROFILE(SMBmkdir);
- return(outsize);
+ END_PROFILE(SMBmkdir);
+ return(outsize);
}
/****************************************************************************
-Static function used by reply_rmdir to delete an entire directory
-tree recursively.
+ Static function used by reply_rmdir to delete an entire directory
+ tree recursively. Return False on ok, True on fail.
****************************************************************************/
static BOOL recursive_rmdir(connection_struct *conn, char *directory)
{
- char *dname = NULL;
- BOOL ret = False;
- void *dirptr = OpenDir(NULL, directory, False);
+ char *dname = NULL;
+ BOOL ret = False;
+ void *dirptr = OpenDir(conn, directory, False);
- if(dirptr == NULL)
- return True;
+ if(dirptr == NULL)
+ return True;
- while((dname = ReadDirName(dirptr)))
- {
- pstring fullname;
- SMB_STRUCT_STAT st;
+ while((dname = ReadDirName(dirptr))) {
+ pstring fullname;
+ SMB_STRUCT_STAT st;
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
- continue;
+ if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+ continue;
- /* Construct the full name. */
- if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
- {
- errno = ENOMEM;
- ret = True;
- break;
- }
- pstrcpy(fullname, directory);
- pstrcat(fullname, "/");
- pstrcat(fullname, dname);
+ /* Construct the full name. */
+ if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
+ errno = ENOMEM;
+ ret = True;
+ break;
+ }
- if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
- {
- ret = True;
- break;
- }
+ pstrcpy(fullname, directory);
+ pstrcat(fullname, "/");
+ pstrcat(fullname, dname);
- if(st.st_mode & S_IFDIR)
- {
- if(recursive_rmdir(conn, fullname)!=0)
- {
- ret = True;
- break;
- }
- if(vfs_rmdir(conn,fullname) != 0)
- {
- ret = True;
- break;
- }
- }
- else if(vfs_unlink(conn,fullname) != 0)
- {
- ret = True;
- break;
- }
- }
- CloseDir(dirptr);
- return ret;
+ if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
+ ret = True;
+ break;
+ }
+
+ if(st.st_mode & S_IFDIR) {
+ if(recursive_rmdir(conn, fullname)!=0) {
+ ret = True;
+ break;
+ }
+ if(vfs_rmdir(conn,fullname) != 0) {
+ ret = True;
+ break;
+ }
+ } else if(vfs_unlink(conn,fullname) != 0) {
+ ret = True;
+ break;
+ }
+ }
+ CloseDir(dirptr);
+ return ret;
}
/****************************************************************************
BOOL rmdir_internals(connection_struct *conn, char *directory)
{
- BOOL ok;
+ BOOL ok;
+
+ ok = (vfs_rmdir(conn,directory) == 0);
+ if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
+ /*
+ * Check to see if the only thing in this directory are
+ * vetoed files/directories. If so then delete them and
+ * retry. If we fail to delete any of them (and we *don't*
+ * do a recursive delete) then fail the rmdir.
+ */
+ BOOL all_veto_files = True;
+ char *dname;
+ void *dirptr = OpenDir(conn, directory, False);
- ok = (vfs_rmdir(conn,directory) == 0);
- if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
- {
- /*
- * Check to see if the only thing in this directory are
- * vetoed files/directories. If so then delete them and
- * retry. If we fail to delete any of them (and we *don't*
- * do a recursive delete) then fail the rmdir.
- */
- BOOL all_veto_files = True;
- char *dname;
- void *dirptr = OpenDir(conn, directory, False);
+ if(dirptr != NULL) {
+ int dirpos = TellDir(dirptr);
+ while ((dname = ReadDirName(dirptr))) {
+ if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+ continue;
+ if(!IS_VETO_PATH(conn, dname)) {
+ all_veto_files = False;
+ break;
+ }
+ }
- if(dirptr != NULL)
- {
- int dirpos = TellDir(dirptr);
- while ((dname = ReadDirName(dirptr)))
- {
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
- continue;
- if(!IS_VETO_PATH(conn, dname))
- {
- all_veto_files = False;
- break;
- }
- }
- if(all_veto_files)
- {
- SeekDir(dirptr,dirpos);
- while ((dname = ReadDirName(dirptr)))
- {
- pstring fullname;
- SMB_STRUCT_STAT st;
+ if(all_veto_files) {
+ SeekDir(dirptr,dirpos);
+ while ((dname = ReadDirName(dirptr))) {
+ pstring fullname;
+ SMB_STRUCT_STAT st;
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
- continue;
+ if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+ continue;
- /* Construct the full name. */
- if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
- {
- errno = ENOMEM;
- break;
- }
- pstrcpy(fullname, directory);
- pstrcat(fullname, "/");
- pstrcat(fullname, dname);
+ /* Construct the full name. */
+ if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
+ errno = ENOMEM;
+ break;
+ }
+
+ pstrcpy(fullname, directory);
+ pstrcat(fullname, "/");
+ pstrcat(fullname, dname);
- if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
- break;
- if(st.st_mode & S_IFDIR)
- {
- if(lp_recursive_veto_delete(SNUM(conn)))
- {
- if(recursive_rmdir(conn, fullname) != 0)
- break;
- }
- if(vfs_rmdir(conn,fullname) != 0)
- break;
- }
- else if(vfs_unlink(conn,fullname) != 0)
- break;
- }
- CloseDir(dirptr);
- /* Retry the rmdir */
- ok = (vfs_rmdir(conn,directory) == 0);
- }
- else
- CloseDir(dirptr);
- }
- else
- errno = ENOTEMPTY;
- }
-
- if (!ok)
- DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
- directory,strerror(errno)));
+ if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
+ break;
+ if(st.st_mode & S_IFDIR) {
+ if(lp_recursive_veto_delete(SNUM(conn))) {
+ if(recursive_rmdir(conn, fullname) != 0)
+ break;
+ }
+ if(vfs_rmdir(conn,fullname) != 0)
+ break;
+ } else if(vfs_unlink(conn,fullname) != 0)
+ break;
+ }
+ CloseDir(dirptr);
+ /* Retry the rmdir */
+ ok = (vfs_rmdir(conn,directory) == 0);
+ } else {
+ CloseDir(dirptr);
+ }
+ } else {
+ errno = ENOTEMPTY;
+ }
+ }
- return ok;
+ if (!ok)
+ DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
+
+ return ok;
}
/****************************************************************************
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBrmdir);
- srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
if (!ok)
{
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ set_bad_path_error(errno, bad_path);
END_PROFILE(SMBrmdir);
return(UNIXERROR(ERRDOS,ERRbadpath));
}
return(True);
}
-/*******************************************************************
-check if a user is allowed to rename a file
-********************************************************************/
-static BOOL can_rename(char *fname,connection_struct *conn)
-{
- SMB_STRUCT_STAT sbuf;
-
- if (!CAN_WRITE(conn)) return(False);
-
- if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
- if (!check_file_sharing(conn,fname,True)) return(False);
- return(True);
-}
-
/****************************************************************************
The guts of the rename command, split out so it may be called by the NT SMB
code.
****************************************************************************/
-int rename_internals(connection_struct *conn,
- char *inbuf, char *outbuf, char *name,
- char *newname, BOOL replace_if_exists)
+
+NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
{
pstring directory;
pstring mask;
BOOL bad_path1 = False;
BOOL bad_path2 = False;
int count=0;
- int error = ERRnoaccess;
- BOOL exists=False;
+ NTSTATUS error = NT_STATUS_OK;
BOOL rc = True;
SMB_STRUCT_STAT sbuf1, sbuf2;
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && is_mangled(mask))
- check_mangled_cache( mask );
+ if (!rc && mangle_is_mangled(mask))
+ mangle_check_cache( mask );
has_wild = ms_has_wild(mask);
/*
* No wildcards - just process the one file.
*/
- BOOL is_short_name = is_8_3(name, True);
+ BOOL is_short_name = mangle_is_8_3(name, True);
/* Add a terminating '/' to the directory name. */
pstrcat(directory,"/");
pstrcpy(newname, tmpstr);
}
- 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",
+ 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",
case_sensitive, case_preserve, short_case_preserve, directory,
newname, newname_last_component, is_short_name));
pstrcpy(p+1, newname_last_component);
}
}
-
- if(replace_if_exists) {
- /*
- * NT SMB specific flag - rename can overwrite
- * file with the same name so don't check for
- * vfs_file_exist().
- */
+
+ resolve_wildcards(directory,newname);
+
+ /*
+ * The source object must exist.
+ */
- if(resolve_wildcards(directory,newname) &&
- can_rename(directory,conn) &&
- !conn->vfs_ops.rename(conn,directory,newname))
- count++;
- } else {
- if (resolve_wildcards(directory,newname) &&
- can_rename(directory,conn) &&
- !vfs_file_exist(conn,newname,NULL) &&
- !conn->vfs_ops.rename(conn,directory,newname))
- count++;
+ if (!vfs_object_exist(conn, directory, &sbuf1)) {
+ DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
+ directory,newname));
+
+ if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
+ /*
+ * Must return different errors depending on whether the parent
+ * directory existed or not.
+ */
+
+ p = strrchr_m(directory, '/');
+ if (!p)
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ *p = '\0';
+ if (vfs_object_exist(conn, directory, NULL))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ error = map_nt_error_from_unix(errno);
+ DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+ nt_errstr(error), directory,newname));
+
+ return error;
}
- DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
- directory,newname));
-
- if (!count) exists = vfs_file_exist(conn,directory,NULL);
- if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
- exists = True;
- error = ERRrename;
+ error = can_rename(directory,conn,&sbuf1);
+
+ if (!NT_STATUS_IS_OK(error)) {
+ DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+ nt_errstr(error), directory,newname));
+ return error;
+ }
+
+ /*
+ * If the src and dest names are identical - including case,
+ * don't do the rename, just return success.
+ */
+
+ if (strcsequal(directory, newname)) {
+ DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
+ return NT_STATUS_OK;
+ }
+
+ if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
+ DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
+ directory,newname));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
}
+
+ if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
+ DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
+ directory,newname));
+ return NT_STATUS_OK;
+ }
+
+ if (errno == ENOTDIR || errno == EISDIR)
+ error = NT_STATUS_OBJECT_NAME_COLLISION;
+ else
+ error = map_nt_error_from_unix(errno);
+
+ DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+ nt_errstr(error), directory,newname));
+
+ return error;
} else {
/*
* Wildcards - process each file that matches.
dirptr = OpenDir(conn, directory, True);
if (dirptr) {
- error = ERRbadfile;
+ error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
if(!mask_match(fname, mask, case_sensitive))
continue;
- error = ERRnoaccess;
+ error = NT_STATUS_ACCESS_DENIED;
slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
- if (!can_rename(fname,conn)) {
+ if (!vfs_object_exist(conn, fname, &sbuf1)) {
+ error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
+ continue;
+ }
+ error = can_rename(fname,conn,&sbuf1);
+ if (!NT_STATUS_IS_OK(error)) {
DEBUG(6,("rename %s refused\n", fname));
continue;
}
if (!replace_if_exists &&
vfs_file_exist(conn,destname, NULL)) {
DEBUG(6,("file_exist %s\n", destname));
- error = 183;
+ error = NT_STATUS_OBJECT_NAME_COLLISION;
continue;
}
}
}
- if (count == 0) {
- if (exists)
- return(ERROR(ERRDOS,error));
- else {
- if((errno == ENOENT) && (bad_path1 || bad_path2)) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- return(UNIXERROR(ERRDOS,error));
- }
+ if (count == 0 && NT_STATUS_IS_OK(error)) {
+ error = map_nt_error_from_unix(errno);
}
- return 0;
+ return error;
}
/****************************************************************************
Reply to a mv.
****************************************************************************/
-int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
+ int dum_buffsize)
{
- int outsize = 0;
- pstring name;
- pstring newname;
- char *p;
-
- START_PROFILE(SMBmv);
-
- p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
- p++;
- p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
-
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
- RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+ int outsize = 0;
+ pstring name;
+ pstring newname;
+ char *p;
+ NTSTATUS status;
- DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
+ START_PROFILE(SMBmv);
- outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
- if(outsize == 0) {
+ p = smb_buf(inbuf) + 1;
+ p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
+ p++;
+ p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
+
+ RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+
+ DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
+
+ status = rename_internals(conn, name, newname, False);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
/*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
-
- process_pending_change_notify_queue((time_t)0);
-
- outsize = set_message(outbuf,0,0,True);
- }
+ * Win2k needs a changenotify request response before it will
+ * update after a rename..
+ */
+ process_pending_change_notify_queue((time_t)0);
+ outsize = set_message(outbuf,0,0,True);
- END_PROFILE(SMBmv);
- return(outsize);
+ END_PROFILE(SMBmv);
+ return(outsize);
}
/*******************************************************************
- copy a file as part of a reply_copy
- ******************************************************************/
+ Copy a file as part of a reply_copy.
+******************************************************************/
static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
int count,BOOL target_is_directory, int *err_ret)
{
- int Access,action;
- SMB_STRUCT_STAT src_sbuf, sbuf2;
- SMB_OFF_T ret=-1;
- files_struct *fsp1,*fsp2;
- pstring dest;
+ int Access,action;
+ SMB_STRUCT_STAT src_sbuf, sbuf2;
+ SMB_OFF_T ret=-1;
+ files_struct *fsp1,*fsp2;
+ pstring dest;
- *err_ret = 0;
+ *err_ret = 0;
- pstrcpy(dest,dest1);
- if (target_is_directory) {
- char *p = strrchr_m(src,'/');
- if (p)
- p++;
- else
- p = src;
- pstrcat(dest,"/");
- pstrcat(dest,p);
- }
+ pstrcpy(dest,dest1);
+ if (target_is_directory) {
+ char *p = strrchr_m(src,'/');
+ if (p)
+ p++;
+ else
+ p = src;
+ pstrcat(dest,"/");
+ pstrcat(dest,p);
+ }
- if (!vfs_file_exist(conn,src,&src_sbuf))
- return(False);
+ if (!vfs_file_exist(conn,src,&src_sbuf))
+ return(False);
- fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
+ fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
- if (!fsp1) {
- return(False);
- }
+ if (!fsp1)
+ return(False);
- if (!target_is_directory && count)
- ofun = FILE_EXISTS_OPEN;
+ if (!target_is_directory && count)
+ ofun = FILE_EXISTS_OPEN;
- vfs_stat(conn,dest,&sbuf2);
- fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
- ofun,src_sbuf.st_mode,0,&Access,&action);
+ if (vfs_stat(conn,dest,&sbuf2) == -1)
+ ZERO_STRUCTP(&sbuf2);
- if (!fsp2) {
- close_file(fsp1,False);
- return(False);
- }
+ fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
+ ofun,src_sbuf.st_mode,0,&Access,&action);
- if ((ofun&3) == 1) {
- if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
- DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
- strerror(errno) ));
- /*
- * Stop the copy from occurring.
- */
- ret = -1;
- src_sbuf.st_size = 0;
- }
- }
+ if (!fsp2) {
+ close_file(fsp1,False);
+ return(False);
+ }
+
+ if ((ofun&3) == 1) {
+ if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
+ DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
+ /*
+ * Stop the copy from occurring.
+ */
+ ret = -1;
+ src_sbuf.st_size = 0;
+ }
+ }
- if (src_sbuf.st_size)
- ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
+ if (src_sbuf.st_size)
+ ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
- close_file(fsp1,False);
- /*
- * As we are opening fsp1 read-only we only expect
- * an error on close on fsp2 if we are out of space.
- * Thus we don't look at the error return from the
- * close of fsp1.
- */
- *err_ret = close_file(fsp2,False);
+ close_file(fsp1,False);
- return(ret == (SMB_OFF_T)src_sbuf.st_size);
-}
+ /* Ensure the modtime is set correctly on the destination file. */
+ fsp2->pending_modtime = src_sbuf.st_mtime;
+ /*
+ * As we are opening fsp1 read-only we only expect
+ * an error on close on fsp2 if we are out of space.
+ * Thus we don't look at the error return from the
+ * close of fsp1.
+ */
+ *err_ret = close_file(fsp2,False);
+ return(ret == (SMB_OFF_T)src_sbuf.st_size);
+}
/****************************************************************************
reply to a file copy.
*directory = *mask = 0;
p = smb_buf(inbuf);
- p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
/* can't currently handle inter share copies XXXX */
DEBUG(3,("Rejecting inter-share copy\n"));
END_PROFILE(SMBcopy);
- return(ERROR(ERRSRV,ERRinvdevice));
+ return ERROR_DOS(ERRSRV,ERRinvdevice);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
if ((flags&1) && target_is_directory) {
END_PROFILE(SMBcopy);
- return(ERROR(ERRDOS,ERRbadfile));
+ return ERROR_DOS(ERRDOS,ERRbadfile);
}
if ((flags&2) && !target_is_directory) {
END_PROFILE(SMBcopy);
- return(ERROR(ERRDOS,ERRbadpath));
+ return ERROR_DOS(ERRDOS,ERRbadpath);
}
if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
/* wants a tree copy! XXXX */
DEBUG(3,("Rejecting tree copy\n"));
END_PROFILE(SMBcopy);
- return(ERROR(ERRSRV,ERRerror));
+ return ERROR_DOS(ERRSRV,ERRerror);
}
p = strrchr_m(name,'/');
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && is_mangled(mask))
- check_mangled_cache( mask );
+ if (!rc && mangle_is_mangled(mask))
+ mangle_check_cache( mask );
has_wild = ms_has_wild(mask);
if (exists) {
END_PROFILE(SMBcopy);
- return(ERROR(ERRDOS,error));
+ return ERROR_DOS(ERRDOS,error);
} else
{
if((errno == ENOENT) && (bad_path1 || bad_path2))
snum = SNUM(conn);
if (!CAN_SETDIR(snum)) {
END_PROFILE(pathworks_setdir);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
if (strlen(newdir) == 0) {
ok = True;
if (!ok) {
END_PROFILE(pathworks_setdir);
- return(ERROR(ERRDOS,ERRbadpath));
+ return ERROR_DOS(ERRDOS,ERRbadpath);
}
outsize = set_message(outbuf,0,0,True);
- CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
+ SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
DEBUG(3,("setdir %s\n", newdir));
if(!large_file_format)
return SVAL(data,SMB_LPID_OFFSET(data_offset));
else
- return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
+ return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
}
/****************************************************************************
return count;
}
+#if !defined(HAVE_LONGLONG)
+/****************************************************************************
+ Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
+****************************************************************************/
+static uint32 map_lock_offset(uint32 high, uint32 low)
+{
+ unsigned int i;
+ uint32 mask = 0;
+ uint32 highcopy = high;
+
+ /*
+ * Try and find out how many significant bits there are in high.
+ */
+
+ for(i = 0; highcopy; i++)
+ highcopy >>= 1;
+
+ /*
+ * We use 31 bits not 32 here as POSIX
+ * lock offsets may not be negative.
+ */
+
+ mask = (~0) << (31 - i);
+
+ if(low & mask)
+ return 0; /* Fail. */
+
+ high <<= (31 - i);
+
+ return (high|low);
+}
+#endif /* !defined(HAVE_LONGLONG) */
+
/****************************************************************************
Get a lock offset, dealing with large offset requests.
****************************************************************************/
int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
- files_struct *fsp = file_fsp(inbuf,smb_vwv2);
- unsigned char locktype = CVAL(inbuf,smb_vwv3);
- unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
- uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
- uint16 num_locks = SVAL(inbuf,smb_vwv7);
- SMB_BIG_UINT count = 0, offset = 0;
- uint16 lock_pid;
- int32 lock_timeout = IVAL(inbuf,smb_vwv4);
- int i;
- char *data;
- uint32 ecode=0, dummy2;
- int eclass=0, dummy1;
- BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
- BOOL err;
- START_PROFILE(SMBlockingX);
-
- CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
-
- data = smb_buf(inbuf);
-
- /* Check if this is an oplock break on a file
- we have granted an oplock on.
- */
- if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
- {
- /* Client can insist on breaking to none. */
- BOOL break_to_none = (oplocklevel == 0);
+ files_struct *fsp = file_fsp(inbuf,smb_vwv2);
+ unsigned char locktype = CVAL(inbuf,smb_vwv3);
+ unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
+ uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
+ uint16 num_locks = SVAL(inbuf,smb_vwv7);
+ SMB_BIG_UINT count = 0, offset = 0;
+ uint16 lock_pid;
+ int32 lock_timeout = IVAL(inbuf,smb_vwv4);
+ int i;
+ char *data;
+ BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
+ BOOL err;
+ NTSTATUS status;
- DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
- (unsigned int)oplocklevel, fsp->fnum ));
+ START_PROFILE(SMBlockingX);
+
+ CHECK_FSP(fsp,conn);
+
+ data = smb_buf(inbuf);
- /*
- * Make sure we have granted an exclusive or batch oplock on this file.
- */
+ if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
+ /* we don't support these - and CANCEL_LOCK makes w2k
+ and XP reboot so I don't really want to be
+ compatible! (tridge) */
+ return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+ }
+
+ /* Check if this is an oplock break on a file
+ we have granted an oplock on.
+ */
+ if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
+ /* Client can insist on breaking to none. */
+ BOOL break_to_none = (oplocklevel == 0);
+
+ DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
+ (unsigned int)oplocklevel, fsp->fnum ));
- if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
- {
- DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
+ /*
+ * Make sure we have granted an exclusive or batch oplock on this file.
+ */
+
+ if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+ DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
- /* if this is a pure oplock break request then don't send a reply */
- if (num_locks == 0 && num_ulocks == 0) {
- END_PROFILE(SMBlockingX);
- return -1;
- } else {
- END_PROFILE(SMBlockingX);
- return ERROR(ERRDOS,ERRlock);
- }
- }
-
- if (remove_oplock(fsp, break_to_none) == False) {
- DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
- fsp->fsp_name ));
- }
-
- /* if this is a pure oplock break request then don't send a reply */
- if (num_locks == 0 && num_ulocks == 0)
- {
- /* Sanity check - ensure a pure oplock break is not a
- chained request. */
- if(CVAL(inbuf,smb_vwv0) != 0xff)
- DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
- (unsigned int)CVAL(inbuf,smb_vwv0) ));
- END_PROFILE(SMBlockingX);
- return -1;
- }
- }
-
- /*
- * We do this check *after* we have checked this is not a oplock break
- * response message. JRA.
- */
-
- release_level_2_oplocks_on_change(fsp);
-
- /* Data now points at the beginning of the list
- of smb_unlkrng structs */
- for(i = 0; i < (int)num_ulocks; i++) {
- lock_pid = get_lock_pid( data, i, large_file_format);
- count = get_lock_count( data, i, large_file_format);
- offset = get_lock_offset( data, i, large_file_format, &err);
-
- /*
- * There is no error code marked "stupid client bug".... :-).
- */
- if(err) {
- END_PROFILE(SMBlockingX);
- return ERROR(ERRDOS,ERRnoaccess);
- }
-
- DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
- (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
-
- if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
- END_PROFILE(SMBlockingX);
- return ERROR(eclass,ecode);
- }
- }
+ /* if this is a pure oplock break request then don't send a reply */
+ if (num_locks == 0 && num_ulocks == 0) {
+ END_PROFILE(SMBlockingX);
+ return -1;
+ } else {
+ END_PROFILE(SMBlockingX);
+ return ERROR_DOS(ERRDOS,ERRlock);
+ }
+ }
- /* Setup the timeout in seconds. */
- lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
+ if (remove_oplock(fsp, break_to_none) == False) {
+ DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
+ fsp->fsp_name ));
+ }
+
+ /* if this is a pure oplock break request then don't send a reply */
+ if (num_locks == 0 && num_ulocks == 0) {
+ /* Sanity check - ensure a pure oplock break is not a
+ chained request. */
+ if(CVAL(inbuf,smb_vwv0) != 0xff)
+ DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
+ (unsigned int)CVAL(inbuf,smb_vwv0) ));
+ END_PROFILE(SMBlockingX);
+ return -1;
+ }
+ }
- /* Now do any requested locks */
- data += ((large_file_format ? 20 : 10)*num_ulocks);
+ /*
+ * We do this check *after* we have checked this is not a oplock break
+ * response message. JRA.
+ */
+
+ release_level_2_oplocks_on_change(fsp);
+
+ /* Data now points at the beginning of the list
+ of smb_unlkrng structs */
+ for(i = 0; i < (int)num_ulocks; i++) {
+ lock_pid = get_lock_pid( data, i, large_file_format);
+ count = get_lock_count( data, i, large_file_format);
+ offset = get_lock_offset( data, i, large_file_format, &err);
+
+ /*
+ * There is no error code marked "stupid client bug".... :-).
+ */
+ if(err) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
+ }
- /* Data now points at the beginning of the list
- of smb_lkrng structs */
+ DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
+ (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
+
+ status = do_unlock(fsp,conn,lock_pid,count,offset);
+ if (NT_STATUS_V(status)) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_NT(status);
+ }
+ }
- for(i = 0; i < (int)num_locks; i++) {
- lock_pid = get_lock_pid( data, i, large_file_format);
- count = get_lock_count( data, i, large_file_format);
- offset = get_lock_offset( data, i, large_file_format, &err);
+ /* Setup the timeout in seconds. */
- /*
- * There is no error code marked "stupid client bug".... :-).
- */
- if(err) {
- END_PROFILE(SMBlockingX);
- return ERROR(ERRDOS,ERRnoaccess);
- }
-
- DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
- (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
-
- if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
- &eclass, &ecode)) {
- if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
- END_PROFILE(SMBlockingX);
- return -1;
+ lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
+
+ /* Now do any requested locks */
+ data += ((large_file_format ? 20 : 10)*num_ulocks);
+
+ /* Data now points at the beginning of the list
+ of smb_lkrng structs */
+
+ for(i = 0; i < (int)num_locks; i++) {
+ lock_pid = get_lock_pid( data, i, large_file_format);
+ count = get_lock_count( data, i, large_file_format);
+ offset = get_lock_offset( data, i, large_file_format, &err);
+
+ /*
+ * There is no error code marked "stupid client bug".... :-).
+ */
+ if(err) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
+ }
+
+ DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
+ (double)offset, (double)count, (unsigned int)lock_pid,
+ fsp->fsp_name, (int)lock_timeout ));
+
+ status = do_lock_spin(fsp,conn,lock_pid, count,offset,
+ ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
+ if (NT_STATUS_V(status)) {
+ if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
+ END_PROFILE(SMBlockingX);
+ return -1;
+ }
+ }
+ break;
+ }
+ }
+
+ /* If any of the above locks failed, then we must unlock
+ all of the previous locks (X/Open spec). */
+ if (i != num_locks && num_locks != 0) {
+ /*
+ * Ensure we don't do a remove on the lock that just failed,
+ * as under POSIX rules, if we have a lock already there, we
+ * will delete it (and we shouldn't) .....
+ */
+ for(i--; i >= 0; i--) {
+ lock_pid = get_lock_pid( data, i, large_file_format);
+ count = get_lock_count( data, i, large_file_format);
+ offset = get_lock_offset( data, i, large_file_format, &err);
+
+ /*
+ * There is no error code marked "stupid client bug".... :-).
+ */
+ if(err) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
+ }
+
+ do_unlock(fsp,conn,lock_pid,count,offset);
+ }
+ END_PROFILE(SMBlockingX);
+ return ERROR_NT(status);
}
- }
- break;
- }
- }
- /* If any of the above locks failed, then we must unlock
- all of the previous locks (X/Open spec). */
- if(i != num_locks && num_locks != 0) {
- /*
- * Ensure we don't do a remove on the lock that just failed,
- * as under POSIX rules, if we have a lock already there, we
- * will delete it (and we shouldn't) .....
- */
- for(i--; i >= 0; i--) {
- lock_pid = get_lock_pid( data, i, large_file_format);
- count = get_lock_count( data, i, large_file_format);
- offset = get_lock_offset( data, i, large_file_format, &err);
-
- /*
- * There is no error code marked "stupid client bug".... :-).
- */
- if(err) {
+ set_message(outbuf,2,0,True);
+
+ DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
+ fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
+
END_PROFILE(SMBlockingX);
- return ERROR(ERRDOS,ERRnoaccess);
- }
-
- do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
- }
- END_PROFILE(SMBlockingX);
- return ERROR(eclass,ecode);
- }
-
- set_message(outbuf,2,0,True);
-
- DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
- fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
-
- END_PROFILE(SMBlockingX);
- return chain_reply(inbuf,outbuf,length,bufsize);
+ return chain_reply(inbuf,outbuf,length,bufsize);
}
-
/****************************************************************************
- reply to a SMBreadbmpx (read block multiplex) request
+ Reply to a SMBreadbmpx (read block multiplex) request.
****************************************************************************/
+
int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
- ssize_t nread = -1;
- ssize_t total_read;
- char *data;
- SMB_OFF_T startpos;
- int outsize;
- size_t maxcount;
- int max_per_packet;
- size_t tcount;
- int pad;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBreadBmpx);
+ ssize_t nread = -1;
+ ssize_t total_read;
+ char *data;
+ SMB_OFF_T startpos;
+ int outsize;
+ size_t maxcount;
+ int max_per_packet;
+ size_t tcount;
+ int pad;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBreadBmpx);
- /* this function doesn't seem to work - disable by default */
- if (!lp_readbmpx()) {
- END_PROFILE(SMBreadBmpx);
- return(ERROR(ERRSRV,ERRuseSTD));
- }
+ /* this function doesn't seem to work - disable by default */
+ if (!lp_readbmpx()) {
+ END_PROFILE(SMBreadBmpx);
+ return ERROR_DOS(ERRSRV,ERRuseSTD);
+ }
- outsize = set_message(outbuf,8,0,True);
+ outsize = set_message(outbuf,8,0,True);
- CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
- CHECK_ERROR(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_READ(fsp);
- startpos = IVAL(inbuf,smb_vwv1);
- maxcount = SVAL(inbuf,smb_vwv3);
+ startpos = IVAL(inbuf,smb_vwv1);
+ maxcount = SVAL(inbuf,smb_vwv3);
- data = smb_buf(outbuf);
- pad = ((long)data)%4;
- if (pad) pad = 4 - pad;
- data += pad;
+ data = smb_buf(outbuf);
+ pad = ((long)data)%4;
+ if (pad)
+ pad = 4 - pad;
+ data += pad;
- max_per_packet = bufsize-(outsize+pad);
- tcount = maxcount;
- total_read = 0;
+ max_per_packet = bufsize-(outsize+pad);
+ tcount = maxcount;
+ total_read = 0;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
- END_PROFILE(SMBreadBmpx);
- return(ERROR(ERRDOS,ERRlock));
- }
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ END_PROFILE(SMBreadBmpx);
+ return ERROR_DOS(ERRDOS,ERRlock);
+ }
- do
- {
- size_t N = MIN(max_per_packet,tcount-total_read);
+ do {
+ size_t N = MIN(max_per_packet,tcount-total_read);
- nread = read_file(fsp,data,startpos,N);
+ nread = read_file(fsp,data,startpos,N);
- if (nread <= 0) nread = 0;
+ if (nread <= 0)
+ nread = 0;
- if (nread < (ssize_t)N)
- tcount = total_read + nread;
+ if (nread < (ssize_t)N)
+ tcount = total_read + nread;
- set_message(outbuf,8,nread,False);
- SIVAL(outbuf,smb_vwv0,startpos);
- SSVAL(outbuf,smb_vwv2,tcount);
- SSVAL(outbuf,smb_vwv6,nread);
- SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
+ set_message(outbuf,8,nread,False);
+ SIVAL(outbuf,smb_vwv0,startpos);
+ SSVAL(outbuf,smb_vwv2,tcount);
+ SSVAL(outbuf,smb_vwv6,nread);
+ SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_readbmpx: send_smb failed.\n");
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("reply_readbmpx: send_smb failed.");
- total_read += nread;
- startpos += nread;
- }
- while (total_read < (ssize_t)tcount);
+ total_read += nread;
+ startpos += nread;
+ } while (total_read < (ssize_t)tcount);
- END_PROFILE(SMBreadBmpx);
- return(-1);
+ END_PROFILE(SMBreadBmpx);
+ return(-1);
}
/****************************************************************************
- reply to a SMBwritebmpx (write block multiplex primary) request
+ Reply to a SMBsetattrE.
****************************************************************************/
-int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- size_t numtowrite;
- ssize_t nwritten = -1;
- int outsize = 0;
- SMB_OFF_T startpos;
- size_t tcount;
- BOOL write_through;
- int smb_doff;
- char *data;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBwriteBmpx);
-
- CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
-
- tcount = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv3);
- write_through = BITSETW(inbuf+smb_vwv7,0);
- numtowrite = SVAL(inbuf,smb_vwv10);
- smb_doff = SVAL(inbuf,smb_vwv11);
-
- data = smb_base(inbuf) + smb_doff;
+ struct utimbuf unix_times;
+ int outsize = 0;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBsetattrE);
- /* If this fails we need to send an SMBwriteC response,
- not an SMBwritebmpx - set this up now so we don't forget */
- CVAL(outbuf,smb_com) = SMBwritec;
+ outsize = set_message(outbuf,0,0,True);
- if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
- END_PROFILE(SMBwriteBmpx);
- return(ERROR(ERRDOS,ERRlock));
- }
+ if(!fsp || (fsp->conn != conn)) {
+ END_PROFILE(SMBgetattrE);
+ return ERROR_DOS(ERRDOS,ERRbadfid);
+ }
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ /*
+ * Convert the DOS times into unix times. Ignore create
+ * time as UNIX can't set this.
+ */
- if(lp_syncalways(SNUM(conn)) || write_through)
- sync_file(conn,fsp);
+ unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
+ unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
- if(nwritten < (ssize_t)numtowrite) {
- END_PROFILE(SMBwriteBmpx);
- return(UNIXERROR(ERRHRD,ERRdiskfull));
- }
+ /*
+ * Patch from Ray Frush <frush@engr.colostate.edu>
+ * Sometimes times are sent as zero - ignore them.
+ */
- /* If the maximum to be written to this file
- is greater than what we just wrote then set
- up a secondary struct to be attached to this
- fd, we will use this to cache error messages etc. */
- if((ssize_t)tcount > nwritten)
- {
- write_bmpx_struct *wbms;
- if(fsp->wbmpx_ptr != NULL)
- wbms = fsp->wbmpx_ptr; /* Use an existing struct */
- else
- wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
- if(!wbms)
- {
- DEBUG(0,("Out of memory in reply_readmpx\n"));
- END_PROFILE(SMBwriteBmpx);
- return(ERROR(ERRSRV,ERRnoresource));
- }
- wbms->wr_mode = write_through;
- wbms->wr_discard = False; /* No errors yet */
- wbms->wr_total_written = nwritten;
- wbms->wr_errclass = 0;
- wbms->wr_error = 0;
- fsp->wbmpx_ptr = wbms;
- }
+ if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
+ /* Ignore request */
+ if( DEBUGLVL( 3 ) ) {
+ dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
+ dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
+ }
+ END_PROFILE(SMBsetattrE);
+ return(outsize);
+ } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
+ /* set modify time = to access time if modify time was 0 */
+ unix_times.modtime = unix_times.actime;
+ }
- /* We are returning successfully, set the message type back to
- SMBwritebmpx */
- CVAL(outbuf,smb_com) = SMBwriteBmpx;
-
- outsize = set_message(outbuf,1,0,True);
-
- SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
+ /* Set the date on this file */
+ if(file_utime(conn, fsp->fsp_name, &unix_times)) {
+ END_PROFILE(SMBsetattrE);
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
+ }
- DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
- fsp->fnum, (int)numtowrite, (int)nwritten ) );
-
- if (write_through && tcount==nwritten) {
- /* we need to send both a primary and a secondary response */
- smb_setlen(outbuf,outsize - 4);
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_writebmpx: send_smb failed.\n");
-
- /* now the secondary */
- outsize = set_message(outbuf,1,0,True);
- CVAL(outbuf,smb_com) = SMBwritec;
- SSVAL(outbuf,smb_vwv0,nwritten);
- }
+ DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
+ fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
- END_PROFILE(SMBwriteBmpx);
- return(outsize);
+ END_PROFILE(SMBsetattrE);
+ return(outsize);
}
+/* Back from the dead for OS/2..... JRA. */
+
/****************************************************************************
- reply to a SMBwritebs (write block multiplex secondary) request
+ Reply to a SMBwritebmpx (write block multiplex primary) request.
****************************************************************************/
-int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+
+int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- size_t numtowrite;
- ssize_t nwritten = -1;
- int outsize = 0;
- SMB_OFF_T startpos;
- size_t tcount;
- BOOL write_through;
- int smb_doff;
- char *data;
- write_bmpx_struct *wbms;
- BOOL send_response = False;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBwriteBs);
+ size_t numtowrite;
+ ssize_t nwritten = -1;
+ int outsize = 0;
+ SMB_OFF_T startpos;
+ size_t tcount;
+ BOOL write_through;
+ int smb_doff;
+ char *data;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBwriteBmpx);
- CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
+ CHECK_ERROR(fsp);
- tcount = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv2);
- numtowrite = SVAL(inbuf,smb_vwv6);
- smb_doff = SVAL(inbuf,smb_vwv7);
+ tcount = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv3);
+ write_through = BITSETW(inbuf+smb_vwv7,0);
+ numtowrite = SVAL(inbuf,smb_vwv10);
+ smb_doff = SVAL(inbuf,smb_vwv11);
- data = smb_base(inbuf) + smb_doff;
+ data = smb_base(inbuf) + smb_doff;
- /* We need to send an SMBwriteC response, not an SMBwritebs */
- CVAL(outbuf,smb_com) = SMBwritec;
+ /* If this fails we need to send an SMBwriteC response,
+ not an SMBwritebmpx - set this up now so we don't forget */
+ SCVAL(outbuf,smb_com,SMBwritec);
- /* This fd should have an auxiliary struct attached,
- check that it does */
- wbms = fsp->wbmpx_ptr;
- if(!wbms) {
- END_PROFILE(SMBwriteBs);
- return(-1);
- }
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
+ END_PROFILE(SMBwriteBmpx);
+ return(ERROR_DOS(ERRDOS,ERRlock));
+ }
- /* If write through is set we can return errors, else we must
- cache them */
- write_through = wbms->wr_mode;
+ nwritten = write_file(fsp,data,startpos,numtowrite);
- /* Check for an earlier error */
- if(wbms->wr_discard) {
- END_PROFILE(SMBwriteBs);
- return -1; /* Just discard the packet */
- }
+ if(lp_syncalways(SNUM(conn)) || write_through)
+ sync_file(conn,fsp);
+
+ if(nwritten < (ssize_t)numtowrite) {
+ END_PROFILE(SMBwriteBmpx);
+ return(UNIXERROR(ERRHRD,ERRdiskfull));
+ }
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ /* If the maximum to be written to this file
+ is greater than what we just wrote then set
+ up a secondary struct to be attached to this
+ fd, we will use this to cache error messages etc. */
- if(lp_syncalways(SNUM(conn)) || write_through)
- sync_file(conn,fsp);
-
- if (nwritten < (ssize_t)numtowrite)
- {
- if(write_through)
- {
- /* We are returning an error - we can delete the aux struct */
- if (wbms) free((char *)wbms);
- fsp->wbmpx_ptr = NULL;
- END_PROFILE(SMBwriteBs);
- return(ERROR(ERRHRD,ERRdiskfull));
- }
- END_PROFILE(SMBwriteBs);
- return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
- }
+ if((ssize_t)tcount > nwritten) {
+ write_bmpx_struct *wbms;
+ if(fsp->wbmpx_ptr != NULL)
+ wbms = fsp->wbmpx_ptr; /* Use an existing struct */
+ else
+ wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
+ if(!wbms) {
+ DEBUG(0,("Out of memory in reply_readmpx\n"));
+ END_PROFILE(SMBwriteBmpx);
+ return(ERROR_DOS(ERRSRV,ERRnoresource));
+ }
+ wbms->wr_mode = write_through;
+ wbms->wr_discard = False; /* No errors yet */
+ wbms->wr_total_written = nwritten;
+ wbms->wr_errclass = 0;
+ wbms->wr_error = 0;
+ fsp->wbmpx_ptr = wbms;
+ }
- /* Increment the total written, if this matches tcount
- we can discard the auxiliary struct (hurrah !) and return a writeC */
- wbms->wr_total_written += nwritten;
- if(wbms->wr_total_written >= tcount)
- {
- if (write_through)
- {
- outsize = set_message(outbuf,1,0,True);
- SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
- send_response = True;
- }
+ /* We are returning successfully, set the message type back to
+ SMBwritebmpx */
+ SCVAL(outbuf,smb_com,SMBwriteBmpx);
+
+ outsize = set_message(outbuf,1,0,True);
+
+ SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
+
+ DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
+ fsp->fnum, (int)numtowrite, (int)nwritten ) );
- free((char *)wbms);
- fsp->wbmpx_ptr = NULL;
- }
+ if (write_through && tcount==nwritten) {
+ /* We need to send both a primary and a secondary response */
+ smb_setlen(outbuf,outsize - 4);
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("reply_writebmpx: send_smb failed.");
- if(send_response) {
- END_PROFILE(SMBwriteBs);
- return(outsize);
- }
+ /* Now the secondary */
+ outsize = set_message(outbuf,1,0,True);
+ SCVAL(outbuf,smb_com,SMBwritec);
+ SSVAL(outbuf,smb_vwv0,nwritten);
+ }
- END_PROFILE(SMBwriteBs);
- return(-1);
+ END_PROFILE(SMBwriteBmpx);
+ return(outsize);
}
-
/****************************************************************************
- reply to a SMBsetattrE
+ Reply to a SMBwritebs (write block multiplex secondary) request.
****************************************************************************/
-int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- struct utimbuf unix_times;
- int outsize = 0;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBsetattrE);
+ size_t numtowrite;
+ ssize_t nwritten = -1;
+ int outsize = 0;
+ SMB_OFF_T startpos;
+ size_t tcount;
+ BOOL write_through;
+ int smb_doff;
+ char *data;
+ write_bmpx_struct *wbms;
+ BOOL send_response = False;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBwriteBs);
- outsize = set_message(outbuf,0,0,True);
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
- CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
+ tcount = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
+ numtowrite = SVAL(inbuf,smb_vwv6);
+ smb_doff = SVAL(inbuf,smb_vwv7);
- /* Convert the DOS times into unix times. Ignore create
- time as UNIX can't set this.
- */
- unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
- unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
-
- /*
- * Patch from Ray Frush <frush@engr.colostate.edu>
- * Sometimes times are sent as zero - ignore them.
- */
+ data = smb_base(inbuf) + smb_doff;
- if ((unix_times.actime == 0) && (unix_times.modtime == 0))
- {
- /* Ignore request */
- if( DEBUGLVL( 3 ) )
- {
- dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
- dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
- }
- END_PROFILE(SMBsetattrE);
- return(outsize);
- }
- else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
- {
- /* set modify time = to access time if modify time was 0 */
- unix_times.modtime = unix_times.actime;
- }
+ /* We need to send an SMBwriteC response, not an SMBwritebs */
+ SCVAL(outbuf,smb_com,SMBwritec);
- /* Set the date on this file */
- if(file_utime(conn, fsp->fsp_name, &unix_times)) {
- END_PROFILE(SMBsetattrE);
- return(ERROR(ERRDOS,ERRnoaccess));
- }
+ /* This fd should have an auxiliary struct attached,
+ check that it does */
+ wbms = fsp->wbmpx_ptr;
+ if(!wbms) {
+ END_PROFILE(SMBwriteBs);
+ return(-1);
+ }
+
+ /* If write through is set we can return errors, else we must cache them */
+ write_through = wbms->wr_mode;
+
+ /* Check for an earlier error */
+ if(wbms->wr_discard) {
+ END_PROFILE(SMBwriteBs);
+ return -1; /* Just discard the packet */
+ }
+
+ nwritten = write_file(fsp,data,startpos,numtowrite);
+
+ if(lp_syncalways(SNUM(conn)) || write_through)
+ sync_file(conn,fsp);
- DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
- fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
+ if (nwritten < (ssize_t)numtowrite) {
+ if(write_through) {
+ /* We are returning an error - we can delete the aux struct */
+ if (wbms)
+ free((char *)wbms);
+ fsp->wbmpx_ptr = NULL;
+ END_PROFILE(SMBwriteBs);
+ return(ERROR_DOS(ERRHRD,ERRdiskfull));
+ }
+ END_PROFILE(SMBwriteBs);
+ return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
+ }
- END_PROFILE(SMBsetattrE);
- return(outsize);
-}
+ /* Increment the total written, if this matches tcount
+ we can discard the auxiliary struct (hurrah !) and return a writeC */
+ wbms->wr_total_written += nwritten;
+ if(wbms->wr_total_written >= tcount) {
+ if (write_through) {
+ outsize = set_message(outbuf,1,0,True);
+ SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
+ send_response = True;
+ }
+ free((char *)wbms);
+ fsp->wbmpx_ptr = NULL;
+ }
+
+ if(send_response) {
+ END_PROFILE(SMBwriteBs);
+ return(outsize);
+ }
+
+ END_PROFILE(SMBwriteBs);
+ return(-1);
+}
/****************************************************************************
- reply to a SMBgetattrE
+ Reply to a SMBgetattrE.
****************************************************************************/
int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- SMB_STRUCT_STAT sbuf;
- int outsize = 0;
- int mode;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBgetattrE);
+ SMB_STRUCT_STAT sbuf;
+ int outsize = 0;
+ int mode;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBgetattrE);
- outsize = set_message(outbuf,11,0,True);
+ outsize = set_message(outbuf,11,0,True);
- CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
+ if(!fsp || (fsp->conn != conn)) {
+ END_PROFILE(SMBgetattrE);
+ return ERROR_DOS(ERRDOS,ERRbadfid);
+ }
- /* Do an fstat on this file */
- if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
- END_PROFILE(SMBgetattrE);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ /* Do an fstat on this file */
+ if(fsp_stat(fsp, &sbuf)) {
+ END_PROFILE(SMBgetattrE);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- mode = dos_mode(conn,fsp->fsp_name,&sbuf);
+ mode = dos_mode(conn,fsp->fsp_name,&sbuf);
- /* Convert the times into dos times. Set create
- date to be last modify date as UNIX doesn't save
- this */
- put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
- put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
- put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
- if (mode & aDIR)
- {
- SIVAL(outbuf,smb_vwv6,0);
- SIVAL(outbuf,smb_vwv8,0);
- }
- else
- {
- SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
- SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
- }
- SSVAL(outbuf,smb_vwv10, mode);
+ /*
+ * Convert the times into dos times. Set create
+ * date to be last modify date as UNIX doesn't save
+ * this.
+ */
+
+ put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
+ put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
+ put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
+
+ if (mode & aDIR) {
+ SIVAL(outbuf,smb_vwv6,0);
+ SIVAL(outbuf,smb_vwv8,0);
+ } else {
+ SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
+ SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
+ }
+ SSVAL(outbuf,smb_vwv10, mode);
- DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
+ DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
- END_PROFILE(SMBgetattrE);
- return(outsize);
+ END_PROFILE(SMBgetattrE);
+ return(outsize);
}