summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/account_pol.c148
-rw-r--r--source3/lib/ads_flags.c150
-rw-r--r--source3/lib/charcnv.c8
-rw-r--r--source3/lib/ctdbd_conn.c2
-rw-r--r--source3/lib/dbwrap_tdb.c2
-rw-r--r--source3/lib/dbwrap_util.c173
-rw-r--r--source3/lib/errmap_unix.c1
-rw-r--r--source3/lib/events.c2
-rw-r--r--source3/lib/gencache.c529
-rw-r--r--source3/lib/ldap_escape.c25
-rw-r--r--source3/lib/netapi/netapi.c1
-rw-r--r--source3/lib/netapi/user.c2
-rw-r--r--source3/lib/smbldap_util.c12
-rw-r--r--source3/lib/system.c4
-rw-r--r--source3/lib/tldap.c6
-rw-r--r--source3/lib/util_sock.c3
-rw-r--r--source3/lib/util_str.c36
-rw-r--r--source3/lib/util_tdb.c19
18 files changed, 604 insertions, 519 deletions
diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c
index 1e435ca53e..f4101e96bc 100644
--- a/source3/lib/account_pol.c
+++ b/source3/lib/account_pol.c
@@ -1,20 +1,20 @@
-/*
+/*
* Unix SMB/CIFS implementation.
* account policy storage
* Copyright (C) Jean François Micouleau 1998-2001.
* Copyright (C) Andrew Bartlett 2002
* Copyright (C) Guenther Deschner 2004-2005
- *
+ *
* 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 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -31,7 +31,7 @@ static struct db_context *db;
struct ap_table {
- int field;
+ enum pdb_policy_type type;
const char *string;
uint32 default_val;
const char *description;
@@ -39,51 +39,51 @@ struct ap_table {
};
static const struct ap_table account_policy_names[] = {
- {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH,
- "Minimal password length (default: 5)",
+ {PDB_POLICY_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH,
+ "Minimal password length (default: 5)",
"sambaMinPwdLength" },
- {AP_PASSWORD_HISTORY, "password history", 0,
- "Length of Password History Entries (default: 0 => off)",
+ {PDB_POLICY_PASSWORD_HISTORY, "password history", 0,
+ "Length of Password History Entries (default: 0 => off)",
"sambaPwdHistoryLength" },
-
- {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0,
+
+ {PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0,
"Force Users to logon for password change (default: 0 => off, 2 => on)",
"sambaLogonToChgPwd" },
-
- {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1,
- "Maximum password age, in seconds (default: -1 => never expire passwords)",
+
+ {PDB_POLICY_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1,
+ "Maximum password age, in seconds (default: -1 => never expire passwords)",
"sambaMaxPwdAge" },
-
- {AP_MIN_PASSWORD_AGE,"minimum password age", 0,
- "Minimal password age, in seconds (default: 0 => allow immediate password change)",
+
+ {PDB_POLICY_MIN_PASSWORD_AGE,"minimum password age", 0,
+ "Minimal password age, in seconds (default: 0 => allow immediate password change)",
"sambaMinPwdAge" },
-
- {AP_LOCK_ACCOUNT_DURATION, "lockout duration", 30,
+
+ {PDB_POLICY_LOCK_ACCOUNT_DURATION, "lockout duration", 30,
"Lockout duration in minutes (default: 30, -1 => forever)",
"sambaLockoutDuration" },
-
- {AP_RESET_COUNT_TIME, "reset count minutes", 30,
- "Reset time after lockout in minutes (default: 30)",
+
+ {PDB_POLICY_RESET_COUNT_TIME, "reset count minutes", 30,
+ "Reset time after lockout in minutes (default: 30)",
"sambaLockoutObservationWindow" },
-
- {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0,
- "Lockout users after bad logon attempts (default: 0 => off)",
+
+ {PDB_POLICY_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0,
+ "Lockout users after bad logon attempts (default: 0 => off)",
"sambaLockoutThreshold" },
-
- {AP_TIME_TO_LOGOUT, "disconnect time", (uint32) -1,
- "Disconnect Users outside logon hours (default: -1 => off, 0 => on)",
- "sambaForceLogoff" },
-
- {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0,
+
+ {PDB_POLICY_TIME_TO_LOGOUT, "disconnect time", (uint32) -1,
+ "Disconnect Users outside logon hours (default: -1 => off, 0 => on)",
+ "sambaForceLogoff" },
+
+ {PDB_POLICY_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0,
"Allow Machine Password changes (default: 0 => off)",
"sambaRefuseMachinePwdChange" },
-
+
{0, NULL, 0, "", NULL}
};
void account_policy_names_list(const char ***names, int *num_names)
-{
+{
const char **nl;
int i, count;
@@ -106,11 +106,11 @@ void account_policy_names_list(const char ***names, int *num_names)
Get the account policy name as a string from its #define'ed number
****************************************************************************/
-const char *decode_account_policy_name(int field)
+const char *decode_account_policy_name(enum pdb_policy_type type)
{
int i;
for (i=0; account_policy_names[i].string; i++) {
- if (field == account_policy_names[i].field) {
+ if (type == account_policy_names[i].type) {
return account_policy_names[i].string;
}
}
@@ -121,11 +121,11 @@ const char *decode_account_policy_name(int field)
Get the account policy LDAP attribute as a string from its #define'ed number
****************************************************************************/
-const char *get_account_policy_attr(int field)
+const char *get_account_policy_attr(enum pdb_policy_type type)
{
int i;
- for (i=0; account_policy_names[i].field; i++) {
- if (field == account_policy_names[i].field) {
+ for (i=0; account_policy_names[i].type; i++) {
+ if (type == account_policy_names[i].type) {
return account_policy_names[i].ldap_attr;
}
}
@@ -136,11 +136,11 @@ const char *get_account_policy_attr(int field)
Get the account policy description as a string from its #define'ed number
****************************************************************************/
-const char *account_policy_get_desc(int field)
+const char *account_policy_get_desc(enum pdb_policy_type type)
{
int i;
for (i=0; account_policy_names[i].string; i++) {
- if (field == account_policy_names[i].field) {
+ if (type == account_policy_names[i].type) {
return account_policy_names[i].description;
}
}
@@ -151,12 +151,12 @@ const char *account_policy_get_desc(int field)
Get the account policy name as a string from its #define'ed number
****************************************************************************/
-int account_policy_name_to_fieldnum(const char *name)
+enum pdb_policy_type account_policy_name_to_typenum(const char *name)
{
int i;
for (i=0; account_policy_names[i].string; i++) {
if (strcmp(name, account_policy_names[i].string) == 0) {
- return account_policy_names[i].field;
+ return account_policy_names[i].type;
}
}
return 0;
@@ -166,35 +166,35 @@ int account_policy_name_to_fieldnum(const char *name)
Get default value for account policy
*****************************************************************************/
-bool account_policy_get_default(int account_policy, uint32 *val)
+bool account_policy_get_default(enum pdb_policy_type type, uint32_t *val)
{
int i;
- for (i=0; account_policy_names[i].field; i++) {
- if (account_policy_names[i].field == account_policy) {
+ for (i=0; account_policy_names[i].type; i++) {
+ if (account_policy_names[i].type == type) {
*val = account_policy_names[i].default_val;
return True;
}
}
- DEBUG(0,("no default for account_policy index %d found. This should never happen\n",
- account_policy));
+ DEBUG(0,("no default for account_policy index %d found. This should never happen\n",
+ type));
return False;
}
/*****************************************************************************
- Set default for a field if it is empty
+ Set default for a type if it is empty
*****************************************************************************/
-static bool account_policy_set_default_on_empty(int account_policy)
+static bool account_policy_set_default_on_empty(enum pdb_policy_type type)
{
uint32 value;
- if (!account_policy_get(account_policy, &value) &&
- !account_policy_get_default(account_policy, &value)) {
+ if (!account_policy_get(type, &value) &&
+ !account_policy_get_default(type, &value)) {
return False;
}
- return account_policy_set(account_policy, value);
+ return account_policy_set(type, value);
}
/*****************************************************************************
@@ -255,9 +255,9 @@ bool init_account_policy(void)
goto cancel;
}
- for (i=0; account_policy_names[i].field; i++) {
+ for (i=0; account_policy_names[i].type; i++) {
- if (!account_policy_set_default_on_empty(account_policy_names[i].field)) {
+ if (!account_policy_set_default_on_empty(account_policy_names[i].type)) {
DEBUG(0,("failed to set default value in account policy tdb\n"));
goto cancel;
}
@@ -299,10 +299,10 @@ bool init_account_policy(void)
}
/*****************************************************************************
-Get an account policy (from tdb)
+Get an account policy (from tdb)
*****************************************************************************/
-bool account_policy_get(int field, uint32 *value)
+bool account_policy_get(enum pdb_policy_type type, uint32_t *value)
{
const char *name;
uint32 regval;
@@ -315,17 +315,17 @@ bool account_policy_get(int field, uint32 *value)
*value = 0;
}
- name = decode_account_policy_name(field);
+ name = decode_account_policy_name(type);
if (name == NULL) {
- DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field));
+ DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", type));
return False;
}
-
+
if (!dbwrap_fetch_uint32(db, name, &regval)) {
- DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for field %d (%s), returning 0\n", field, name));
+ DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for type %d (%s), returning 0\n", type, name));
return False;
}
-
+
if (value) {
*value = regval;
}
@@ -336,10 +336,10 @@ bool account_policy_get(int field, uint32 *value)
/****************************************************************************
-Set an account policy (in tdb)
+Set an account policy (in tdb)
****************************************************************************/
-bool account_policy_set(int field, uint32 value)
+bool account_policy_set(enum pdb_policy_type type, uint32_t value)
{
const char *name;
NTSTATUS status;
@@ -348,36 +348,36 @@ bool account_policy_set(int field, uint32 value)
return False;
}
- name = decode_account_policy_name(field);
+ name = decode_account_policy_name(type);
if (name == NULL) {
- DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field));
+ DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", type));
return False;
}
status = dbwrap_trans_store_uint32(db, name, value);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("store_uint32 failed for field %d (%s) on value "
- "%u: %s\n", field, name, value, nt_errstr(status)));
+ DEBUG(1, ("store_uint32 failed for type %d (%s) on value "
+ "%u: %s\n", type, name, value, nt_errstr(status)));
return False;
}
DEBUG(10,("account_policy_set: name: %s, value: %d\n", name, value));
-
+
return True;
}
/****************************************************************************
-Set an account policy in the cache
+Set an account policy in the cache
****************************************************************************/
-bool cache_account_policy_set(int field, uint32 value)
+bool cache_account_policy_set(enum pdb_policy_type type, uint32_t value)
{
const char *policy_name = NULL;
char *cache_key = NULL;
char *cache_value = NULL;
bool ret = False;
- policy_name = decode_account_policy_name(field);
+ policy_name = decode_account_policy_name(type);
if (policy_name == NULL) {
DEBUG(0,("cache_account_policy_set: no policy found\n"));
return False;
@@ -404,17 +404,17 @@ bool cache_account_policy_set(int field, uint32 value)
}
/*****************************************************************************
-Get an account policy from the cache
+Get an account policy from the cache
*****************************************************************************/
-bool cache_account_policy_get(int field, uint32 *value)
+bool cache_account_policy_get(enum pdb_policy_type type, uint32_t *value)
{
const char *policy_name = NULL;
char *cache_key = NULL;
char *cache_value = NULL;
bool ret = False;
- policy_name = decode_account_policy_name(field);
+ policy_name = decode_account_policy_name(type);
if (policy_name == NULL) {
DEBUG(0,("cache_account_policy_set: no policy found\n"));
return False;
diff --git a/source3/lib/ads_flags.c b/source3/lib/ads_flags.c
deleted file mode 100644
index a8fa062f2a..0000000000
--- a/source3/lib/ads_flags.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- ads (active directory) utility library
-
- Copyright (C) Stefan (metze) Metzmacher 2002
- Copyright (C) Andrew Tridgell 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-
-/*
-translated the ACB_CTRL Flags to UserFlags (userAccountControl)
-*/
-uint32 ads_acb2uf(uint32 acb)
-{
- uint32 uf = 0x00000000;
-
- if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE;
- if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED;
- if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD;
- if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT;
- if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT;
- if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT;
- if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT;
- if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT;
- if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT;
- if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD;
- if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT;
- if (acb & ACB_USE_DES_KEY_ONLY) uf |= UF_USE_DES_KEY_ONLY;
- if (acb & ACB_SMARTCARD_REQUIRED) uf |= UF_SMARTCARD_REQUIRED;
- if (acb & ACB_TRUSTED_FOR_DELEGATION) uf |= UF_TRUSTED_FOR_DELEGATION;
- if (acb & ACB_DONT_REQUIRE_PREAUTH) uf |= UF_DONT_REQUIRE_PREAUTH;
- if (acb & ACB_NO_AUTH_DATA_REQD) uf |= UF_NO_AUTH_DATA_REQUIRED;
- if (acb & ACB_NOT_DELEGATED) uf |= UF_NOT_DELEGATED;
- if (acb & ACB_ENC_TXT_PWD_ALLOWED) uf |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED;
-
- return uf;
-}
-
-/*
-translated the UserFlags (userAccountControl) to ACB_CTRL Flags
-*/
-uint32 ads_uf2acb(uint32 uf)
-{
- uint32 acb = 0x00000000;
-
- if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED;
- if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ;
- if (uf & UF_PASSWD_NOTREQD) acb |= ACB_PWNOTREQ;
- if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS;
- if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP;
- if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK;
- if (uf & UF_USE_DES_KEY_ONLY) acb |= ACB_USE_DES_KEY_ONLY;
- if (uf & UF_SMARTCARD_REQUIRED) acb |= ACB_SMARTCARD_REQUIRED;
- if (uf & UF_TRUSTED_FOR_DELEGATION) acb |= ACB_TRUSTED_FOR_DELEGATION;
- if (uf & UF_DONT_REQUIRE_PREAUTH) acb |= ACB_DONT_REQUIRE_PREAUTH;
- if (uf & UF_NO_AUTH_DATA_REQUIRED) acb |= ACB_NO_AUTH_DATA_REQD;
- if (uf & UF_NOT_DELEGATED) acb |= ACB_NOT_DELEGATED;
- if (uf & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED) acb |= ACB_ENC_TXT_PWD_ALLOWED;
-
- switch (uf & UF_ACCOUNT_TYPE_MASK)
- {
- case UF_TEMP_DUPLICATE_ACCOUNT: acb |= ACB_TEMPDUP;break;
- case UF_NORMAL_ACCOUNT: acb |= ACB_NORMAL;break;
- case UF_INTERDOMAIN_TRUST_ACCOUNT: acb |= ACB_DOMTRUST;break;
- case UF_WORKSTATION_TRUST_ACCOUNT: acb |= ACB_WSTRUST;break;
- case UF_SERVER_TRUST_ACCOUNT: acb |= ACB_SVRTRUST;break;
- /*Fix Me: what should we do here? */
- default: acb |= ACB_NORMAL;break;
- }
-
- return acb;
-}
-
-/*
-get the accountType from the UserFlags
-*/
-uint32 ads_uf2atype(uint32 uf)
-{
- uint32 atype = 0x00000000;
-
- if (uf & UF_NORMAL_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT;
- else if (uf & UF_TEMP_DUPLICATE_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT;
- else if (uf & UF_SERVER_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST;
- else if (uf & UF_WORKSTATION_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST;
- else if (uf & UF_INTERDOMAIN_TRUST_ACCOUNT) atype = ATYPE_INTERDOMAIN_TRUST;
-
- return atype;
-}
-
-/*
-get the accountType from the groupType
-*/
-uint32 ads_gtype2atype(uint32 gtype)
-{
- uint32 atype = 0x00000000;
-
- switch(gtype) {
- case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
- atype = ATYPE_SECURITY_LOCAL_GROUP;
- break;
- case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
- atype = ATYPE_SECURITY_LOCAL_GROUP;
- break;
- case GTYPE_SECURITY_GLOBAL_GROUP:
- atype = ATYPE_SECURITY_GLOBAL_GROUP;
- break;
-
- case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
- atype = ATYPE_DISTRIBUTION_GLOBAL_GROUP;
- break;
- case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
- atype = ATYPE_DISTRIBUTION_UNIVERSAL_GROUP;
- break;
- case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
- atype = ATYPE_DISTRIBUTION_LOCAL_GROUP;
- break;
- }
-
- return atype;
-}
-
-/* turn a sAMAccountType into a SID_NAME_USE */
-enum lsa_SidType ads_atype_map(uint32 atype)
-{
- switch (atype & 0xF0000000) {
- case ATYPE_GLOBAL_GROUP:
- return SID_NAME_DOM_GRP;
- case ATYPE_SECURITY_LOCAL_GROUP:
- return SID_NAME_ALIAS;
- case ATYPE_ACCOUNT:
- return SID_NAME_USER;
- default:
- DEBUG(1,("hmm, need to map account type 0x%x\n", atype));
- }
- return SID_NAME_UNKNOWN;
-}
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c
index a1663c1f38..272f107138 100644
--- a/source3/lib/charcnv.c
+++ b/source3/lib/charcnv.c
@@ -753,7 +753,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
size_t size;
smb_ucs2_t *buffer;
- if (!push_ucs2_talloc(NULL, &buffer, src, &size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
return (size_t)-1;
}
@@ -837,7 +837,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
size_t size;
smb_ucs2_t *buffer = NULL;
- if (!convert_string_talloc(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
+ if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
(void **)(void *)&buffer, &size,
True))
{
@@ -951,7 +951,7 @@ size_t push_ascii_nstring(void *dest, const char *src)
smb_ucs2_t *buffer;
conv_silent = True;
- if (!push_ucs2_talloc(NULL, &buffer, src, &buffer_len)) {
+ if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &buffer_len)) {
smb_panic("failed to create UCS2 buffer");
}
@@ -1268,7 +1268,7 @@ static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
}
if (flags & STR_UPPER) {
- tmpbuf = strupper_talloc(NULL, src);
+ tmpbuf = strupper_talloc(talloc_tos(), src);
if (!tmpbuf) {
return (size_t)-1;
}
diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c
index dde377581b..449e049ffa 100644
--- a/source3/lib/ctdbd_conn.c
+++ b/source3/lib/ctdbd_conn.c
@@ -358,7 +358,7 @@ static NTSTATUS ctdb_read_req(struct ctdbd_connection *conn, uint32 reqid,
goto next_pkt;
}
- if (!(msg_state = TALLOC_P(NULL, struct deferred_msg_state))) {
+ if (!(msg_state = TALLOC_P(talloc_autofree_context(), struct deferred_msg_state))) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(hdr);
goto next_pkt;
diff --git a/source3/lib/dbwrap_tdb.c b/source3/lib/dbwrap_tdb.c
index c71e073b41..297a351764 100644
--- a/source3/lib/dbwrap_tdb.c
+++ b/source3/lib/dbwrap_tdb.c
@@ -94,7 +94,7 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db,
/* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
if(DEBUGLEVEL >= 10) {
- char *keystr = hex_encode_talloc(NULL, (unsigned char*)key.dptr, key.dsize);
+ char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize);
DEBUG(10, (DEBUGLEVEL > 10
? "Locking key %s\n" : "Locking key %.20s\n",
keystr));
diff --git a/source3/lib/dbwrap_util.c b/source3/lib/dbwrap_util.c
index 3be3a49e7d..c3ab93c4df 100644
--- a/source3/lib/dbwrap_util.c
+++ b/source3/lib/dbwrap_util.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
Utility functions for the dbwrap API
Copyright (C) Volker Lendecke 2007
+ Copyright (C) Michael Adam 2009
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
@@ -178,96 +179,77 @@ int32 dbwrap_change_int32_atomic(struct db_context *db, const char *keystr,
return 0;
}
-NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
- int flag)
+struct dbwrap_store_context {
+ TDB_DATA *key;
+ TDB_DATA *dbuf;
+ int flag;
+};
+
+static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
{
- int res;
struct db_record *rec = NULL;
NTSTATUS status;
+ struct dbwrap_store_context *store_ctx;
- res = db->transaction_start(db);
- if (res != 0) {
- DEBUG(5, ("transaction_start failed\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
+ store_ctx = (struct dbwrap_store_context *)private_data;
- rec = db->fetch_locked(db, talloc_tos(), key);
+ rec = db->fetch_locked(db, talloc_tos(), *(store_ctx->key));
if (rec == NULL) {
DEBUG(5, ("fetch_locked failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto cancel;
+ return NT_STATUS_NO_MEMORY;
}
- status = rec->store(rec, dbuf, flag);
+ status = rec->store(rec, *(store_ctx->dbuf), store_ctx->flag);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("store returned %s\n", nt_errstr(status)));
- goto cancel;
}
TALLOC_FREE(rec);
+ return status;
+}
- res = db->transaction_commit(db);
- if (res != 0) {
- DEBUG(5, ("tdb_transaction_commit failed\n"));
- status = NT_STATUS_INTERNAL_DB_CORRUPTION;
- TALLOC_FREE(rec);
- return status;
- }
+NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
+ int flag)
+{
+ NTSTATUS status;
+ struct dbwrap_store_context store_ctx;
- return NT_STATUS_OK;
+ store_ctx.key = &key;
+ store_ctx.dbuf = &dbuf;
+ store_ctx.flag = flag;
- cancel:
- TALLOC_FREE(rec);
+ status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
- if (db->transaction_cancel(db) != 0) {
- smb_panic("Cancelling transaction failed");
- }
return status;
}
-NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
+static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
{
- int res;
- struct db_record *rec = NULL;
NTSTATUS status;
+ struct db_record *rec;
+ TDB_DATA *key = (TDB_DATA *)private_data;
- res = db->transaction_start(db);
- if (res != 0) {
- DEBUG(5, ("transaction_start failed\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- rec = db->fetch_locked(db, talloc_tos(), key);
+ rec = db->fetch_locked(db, talloc_tos(), *key);
if (rec == NULL) {
DEBUG(5, ("fetch_locked failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto cancel;
+ return NT_STATUS_NO_MEMORY;
}
status = rec->delete_rec(rec);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status)));
- goto cancel;
}
- TALLOC_FREE(rec);
-
- res = db->transaction_commit(db);
- if (res != 0) {
- DEBUG(5, ("tdb_transaction_commit failed\n"));
- status = NT_STATUS_INTERNAL_DB_CORRUPTION;
- TALLOC_FREE(rec);
- return status;
- }
+ talloc_free(rec);
+ return status;
+}
- return NT_STATUS_OK;
+NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
+{
+ NTSTATUS status;
- cancel:
- TALLOC_FREE(rec);
+ status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
- if (db->transaction_cancel(db) != 0) {
- smb_panic("Cancelling transaction failed");
- }
return status;
}
@@ -307,3 +289,86 @@ NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
{
return dbwrap_trans_delete(db, string_term_tdb_data(key));
}
+
+/**
+ * Wrap db action(s) into a transaction.
+ */
+NTSTATUS dbwrap_trans_do(struct db_context *db,
+ NTSTATUS (*action)(struct db_context *, void *),
+ void *private_data)
+{
+ int res;
+ NTSTATUS status;
+
+ res = db->transaction_start(db);
+ if (res != 0) {
+ DEBUG(5, ("transaction_start failed\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ status = action(db, private_data);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (db->transaction_cancel(db) != 0) {
+ smb_panic("Cancelling transaction failed");
+ }
+ return status;
+ }
+
+ res = db->transaction_commit(db);
+ if (res == 0) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(2, ("transaction_commit failed\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+}
+
+NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
+{
+ char *key_upper;
+ NTSTATUS status;
+
+ key_upper = talloc_strdup_upper(talloc_tos(), key);
+ if (key_upper == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = dbwrap_delete_bystring(db, key_upper);
+
+ talloc_free(key_upper);
+ return status;
+}
+
+NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
+ TDB_DATA data, int flags)
+{
+ char *key_upper;
+ NTSTATUS status;
+
+ key_upper = talloc_strdup_upper(talloc_tos(), key);
+ if (key_upper == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = dbwrap_store_bystring(db, key_upper, data, flags);
+
+ talloc_free(key_upper);
+ return status;
+}
+
+TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
+ const char *key)
+{
+ char *key_upper;
+ TDB_DATA result;
+
+ key_upper = talloc_strdup_upper(talloc_tos(), key);
+ if (key_upper == NULL) {
+ return make_tdb_data(NULL, 0);
+ }
+
+ result = dbwrap_fetch_bystring(db, mem_ctx, key_upper);
+
+ talloc_free(key_upper);
+ return result;
+}
diff --git a/source3/lib/errmap_unix.c b/source3/lib/errmap_unix.c
index 0c39a572ad..00c5475394 100644
--- a/source3/lib/errmap_unix.c
+++ b/source3/lib/errmap_unix.c
@@ -40,6 +40,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
{ EISDIR, ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY},
{ EMLINK, ERRDOS, ERRgeneral, NT_STATUS_TOO_MANY_LINKS },
{ EINTR, ERRHRD, ERRgeneral, NT_STATUS_RETRY },
+ { ENOSYS, ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED },
#ifdef ELOOP
{ ELOOP, ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND },
#endif
diff --git a/source3/lib/events.c b/source3/lib/events.c
index 08debb4252..7a06ad0829 100644
--- a/source3/lib/events.c
+++ b/source3/lib/events.c
@@ -286,7 +286,7 @@ static void s3_event_debug(void *context, enum tevent_debug_level level,
samba_level = 2;
break;
case TEVENT_DEBUG_TRACE:
- samba_level = 10;
+ samba_level = 11;
break;
};
diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c
index 7f133f20b0..ee1f4b70b3 100644
--- a/source3/lib/gencache.c
+++ b/source3/lib/gencache.c
@@ -26,12 +26,13 @@
#define DBGC_CLASS DBGC_TDB
#define TIMEOUT_LEN 12
-#define CACHE_DATA_FMT "%12u/%s"
+#define CACHE_DATA_FMT "%12u/"
#define READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us"
#define BLOB_TYPE "DATA_BLOB"
#define BLOB_TYPE_LEN 9
-static TDB_CONTEXT *cache;
+static struct tdb_context *cache;
+static struct tdb_context *cache_notrans;
/**
* @file gencache.c
@@ -49,9 +50,10 @@ static TDB_CONTEXT *cache;
* false on failure
**/
-bool gencache_init(void)
+static bool gencache_init(void)
{
char* cache_fname = NULL;
+ int open_flags = O_RDWR|O_CREAT;
/* skip file open if it's already opened */
if (cache) return True;
@@ -60,11 +62,12 @@ bool gencache_init(void)
DEBUG(5, ("Opening cache file at %s\n", cache_fname));
- cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT,
- O_RDWR|O_CREAT, 0644);
+ cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, open_flags, 0644);
if (!cache && (errno == EACCES)) {
- cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDONLY, 0644);
+ open_flags = O_RDONLY;
+ cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, open_flags,
+ 0644);
if (cache) {
DEBUG(5, ("gencache_init: Opening cache file %s read-only.\n", cache_fname));
}
@@ -74,65 +77,123 @@ bool gencache_init(void)
DEBUG(5, ("Attempt to open gencache.tdb has failed.\n"));
return False;
}
- return True;
-}
+ cache_fname = lock_path("gencache_notrans.tdb");
-/**
- * Cache shutdown function. Closes opened cache tdb file.
- *
- * @return true on successful closing the cache or
- * false on failure during cache shutdown
- **/
+ DEBUG(5, ("Opening cache file at %s\n", cache_fname));
-bool gencache_shutdown(void)
-{
- int ret;
- /* tdb_close routine returns -1 on error */
- if (!cache) return False;
- DEBUG(5, ("Closing cache file\n"));
- ret = tdb_close(cache);
- cache = NULL;
- return ret != -1;
+ cache_notrans = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST,
+ open_flags, 0644);
+ if (cache_notrans == NULL) {
+ DEBUG(5, ("Opening %s failed: %s\n", cache_fname,
+ strerror(errno)));
+ tdb_close(cache);
+ return false;
+ }
+
+ return True;
}
+static TDB_DATA last_stabilize_key(void)
+{
+ TDB_DATA result;
+ result.dptr = (uint8_t *)"@LAST_STABILIZED";
+ result.dsize = 17;
+ return result;
+}
/**
* Set an entry in the cache file. If there's no such
* one, then add it.
*
* @param keystr string that represents a key of this entry
- * @param value text representation value being cached
+ * @param blob DATA_BLOB value being cached
* @param timeout time when the value is expired
*
* @retval true when entry is successfuly stored
* @retval false on failure
**/
-bool gencache_set(const char *keystr, const char *value, time_t timeout)
+bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob,
+ time_t timeout)
{
int ret;
TDB_DATA databuf;
- char* valstr = NULL;
+ char* val;
+ time_t last_stabilize;
+ static int writecount;
+
+ if (tdb_data_cmp(string_term_tdb_data(keystr),
+ last_stabilize_key()) == 0) {
+ DEBUG(10, ("Can't store %s as a key\n", keystr));
+ return false;
+ }
- /* fail completely if get null pointers passed */
- SMB_ASSERT(keystr && value);
+ if ((keystr == NULL) || (blob == NULL)) {
+ return false;
+ }
if (!gencache_init()) return False;
- if (asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value) == -1) {
+ val = talloc_asprintf(talloc_tos(), CACHE_DATA_FMT, (int)timeout);
+ if (val == NULL) {
return False;
}
+ val = talloc_realloc(NULL, val, char, talloc_array_length(val)-1);
+ if (val == NULL) {
+ return false;
+ }
+ val = (char *)talloc_append_blob(NULL, val, *blob);
+ if (val == NULL) {
+ return false;
+ }
- databuf = string_term_tdb_data(valstr);
- DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
- " %s (%d seconds %s)\n", keystr, value,ctime(&timeout),
+ DEBUG(10, ("Adding cache entry with key = %s and timeout ="
+ " %s (%d seconds %s)\n", keystr, ctime(&timeout),
(int)(timeout - time(NULL)),
timeout > time(NULL) ? "ahead" : "in the past"));
- ret = tdb_store_bystring(cache, keystr, databuf, 0);
- SAFE_FREE(valstr);
+ ret = tdb_store_bystring(
+ cache_notrans, keystr,
+ make_tdb_data((uint8_t *)val, talloc_array_length(val)),
+ 0);
+ TALLOC_FREE(val);
+ if (ret != 0) {
+ return false;
+ }
+
+ /*
+ * Every 100 writes within a single process, stabilize the cache with
+ * a transaction. This is done to prevent a single transaction to
+ * become huge and chew lots of memory.
+ */
+ writecount += 1;
+ if (writecount > lp_parm_int(-1, "gencache", "stabilize_count", 100)) {
+ gencache_stabilize();
+ writecount = 0;
+ goto done;
+ }
+
+ /*
+ * Every 5 minutes, call gencache_stabilize() to not let grow
+ * gencache_notrans.tdb too large.
+ */
+
+ last_stabilize = 0;
+ databuf = tdb_fetch(cache_notrans, last_stabilize_key());
+ if ((databuf.dptr != NULL)
+ && (databuf.dptr[databuf.dsize-1] == '\0')) {
+ last_stabilize = atoi((char *)databuf.dptr);
+ SAFE_FREE(databuf.dptr);
+ }
+ if ((last_stabilize
+ + lp_parm_int(-1, "gencache", "stabilize_interval", 300))
+ < time(NULL)) {
+ gencache_stabilize();
+ }
+
+done:
return ret == 0;
}
@@ -147,26 +208,63 @@ bool gencache_set(const char *keystr, const char *value, time_t timeout)
bool gencache_del(const char *keystr)
{
- int ret;
+ bool exists;
+ bool ret = false;
+ char *value;
- /* fail completely if get null pointers passed */
- SMB_ASSERT(keystr);
+ if (keystr == NULL) {
+ return false;
+ }
if (!gencache_init()) return False;
DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr));
- ret = tdb_delete_bystring(cache, keystr);
- return ret == 0;
+ if (tdb_lock_bystring(cache_notrans, keystr) == -1) {
+ DEBUG(5, ("Could not lock key for %s\n", keystr));
+ return false;
+ }
+
+ /*
+ * We delete an element by setting its timeout to 0. This way we don't
+ * have to do a transaction on gencache.tdb every time we delete an
+ * element.
+ */
+
+ exists = gencache_get(keystr, &value, NULL);
+ if (exists) {
+ SAFE_FREE(value);
+ ret = gencache_set(keystr, "", 0);
+ }
+ tdb_unlock_bystring(cache_notrans, keystr);
+ return ret;
}
+static bool gencache_pull_timeout(char *val, time_t *pres, char **pendptr)
+{
+ time_t res;
+ char *endptr;
+
+ res = strtol(val, &endptr, 10);
+
+ if ((endptr == NULL) || (*endptr != '/')) {
+ DEBUG(2, ("Invalid gencache data format: %s\n", val));
+ return false;
+ }
+ if (pres != NULL) {
+ *pres = res;
+ }
+ if (pendptr != NULL) {
+ *pendptr = endptr;
+ }
+ return true;
+}
/**
* Get existing entry from the cache file.
*
* @param keystr string that represents a key of this entry
- * @param valstr buffer that is allocated and filled with the entry value
- * buffer's disposing must be done outside
+ * @param blob DATA_BLOB that is filled with entry's blob
* @param timeout pointer to a time_t that is filled with entry's
* timeout
*
@@ -174,31 +272,40 @@ bool gencache_del(const char *keystr)
* @retval False for failure
**/
-bool gencache_get(const char *keystr, char **valstr, time_t *timeout)
+bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob,
+ time_t *timeout)
{
TDB_DATA databuf;
time_t t;
char *endptr;
- /* fail completely if get null pointers passed */
- SMB_ASSERT(keystr);
+ if (keystr == NULL) {
+ return false;
+ }
+
+ if (tdb_data_cmp(string_term_tdb_data(keystr),
+ last_stabilize_key()) == 0) {
+ DEBUG(10, ("Can't get %s as a key\n", keystr));
+ return false;
+ }
if (!gencache_init()) {
return False;
}
- databuf = tdb_fetch_bystring(cache, keystr);
+ databuf = tdb_fetch_bystring(cache_notrans, keystr);
if (databuf.dptr == NULL) {
- DEBUG(10, ("Cache entry with key = %s couldn't be found\n",
+ databuf = tdb_fetch_bystring(cache, keystr);
+ }
+
+ if (databuf.dptr == NULL) {
+ DEBUG(10, ("Cache entry with key = %s couldn't be found \n",
keystr));
return False;
}
- t = strtol((const char *)databuf.dptr, &endptr, 10);
-
- if ((endptr == NULL) || (*endptr != '/')) {
- DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr));
+ if (!gencache_pull_timeout((char *)databuf.dptr, &t, &endptr)) {
SAFE_FREE(databuf.dptr);
return False;
}
@@ -207,20 +314,33 @@ bool gencache_get(const char *keystr, char **valstr, time_t *timeout)
"timeout = %s", t > time(NULL) ? "valid" :
"expired", keystr, endptr+1, ctime(&t)));
+ if (t == 0) {
+ /* Deleted */
+ SAFE_FREE(databuf.dptr);
+ return False;
+ }
+
if (t <= time(NULL)) {
- /* We're expired, delete the entry */
- tdb_delete_bystring(cache, keystr);
+ /*
+ * We're expired, delete the entry. We can't use gencache_del
+ * here, because that uses gencache_get_data_blob for checking
+ * the existence of a record. We know the thing exists and
+ * directly store an empty value with 0 timeout.
+ */
+ gencache_set(keystr, "", 0);
SAFE_FREE(databuf.dptr);
return False;
}
- if (valstr) {
- *valstr = SMB_STRDUP(endptr+1);
- if (*valstr == NULL) {
+ if (blob != NULL) {
+ *blob = data_blob(
+ endptr+1,
+ databuf.dsize - PTR_DIFF(endptr+1, databuf.dptr));
+ if (blob->data == NULL) {
SAFE_FREE(databuf.dptr);
- DEBUG(0, ("strdup failed\n"));
+ DEBUG(0, ("memdup failed\n"));
return False;
}
}
@@ -234,155 +354,192 @@ bool gencache_get(const char *keystr, char **valstr, time_t *timeout)
return True;
}
+struct stabilize_state {
+ bool written;
+ bool error;
+};
+static int stabilize_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val,
+ void *priv);
+
/**
- * Get existing entry from the cache file.
- *
- * @param keystr string that represents a key of this entry
- * @param blob DATA_BLOB that is filled with entry's blob
- * @param expired pointer to a bool that indicates whether the entry is expired
+ * Stabilize gencache
*
- * @retval true when entry is successfuly fetched
- * @retval False for failure
- **/
+ * Migrate the clear-if-first gencache data to the stable,
+ * transaction-based gencache.tdb
+ */
-bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, bool *expired)
+bool gencache_stabilize(void)
{
- TDB_DATA databuf;
- time_t t;
- char *blob_type;
- unsigned char *buf = NULL;
- bool ret = False;
- fstring valstr;
- int buflen = 0, len = 0, blob_len = 0;
- unsigned char *blob_buf = NULL;
-
- /* fail completely if get null pointers passed */
- SMB_ASSERT(keystr);
+ struct stabilize_state state;
+ int res;
+ char *now;
if (!gencache_init()) {
- return False;
+ return false;
}
- databuf = tdb_fetch_bystring(cache, keystr);
- if (!databuf.dptr) {
- DEBUG(10,("Cache entry with key = %s couldn't be found\n",
- keystr));
- return False;
+ res = tdb_transaction_start(cache);
+ if (res == -1) {
+ DEBUG(10, ("Could not start transaction on gencache.tdb: "
+ "%s\n", tdb_errorstr(cache)));
+ return false;
+ }
+ res = tdb_transaction_start(cache_notrans);
+ if (res == -1) {
+ tdb_transaction_cancel(cache);
+ DEBUG(10, ("Could not start transaction on "
+ "gencache_notrans.tdb: %s\n",
+ tdb_errorstr(cache_notrans)));
+ return false;
}
- buf = (unsigned char *)databuf.dptr;
- buflen = databuf.dsize;
+ state.error = false;
+ state.written = false;
- len += tdb_unpack(buf+len, buflen-len, "fB",
- &valstr,
- &blob_len, &blob_buf);
- if (len == -1) {
- goto out;
+ res = tdb_traverse(cache_notrans, stabilize_fn, &state);
+ if ((res == -1) || state.error) {
+ if ((tdb_transaction_cancel(cache_notrans) == -1)
+ || (tdb_transaction_cancel(cache) == -1)) {
+ smb_panic("tdb_transaction_cancel failed\n");
+ }
+ return false;
}
- t = strtol(valstr, &blob_type, 10);
+ if (!state.written) {
+ if ((tdb_transaction_cancel(cache_notrans) == -1)
+ || (tdb_transaction_cancel(cache) == -1)) {
+ smb_panic("tdb_transaction_cancel failed\n");
+ }
+ return true;
+ }
- if (strcmp(blob_type+1, BLOB_TYPE) != 0) {
- goto out;
+ res = tdb_transaction_commit(cache);
+ if (res == -1) {
+ DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: "
+ "%s\n", tdb_errorstr(cache)));
+ if (tdb_transaction_cancel(cache_notrans) == -1) {
+ smb_panic("tdb_transaction_cancel failed\n");
+ }
+ return false;
}
- DEBUG(10,("Returning %s cache entry: key = %s, "
- "timeout = %s", t > time(NULL) ? "valid" :
- "expired", keystr, ctime(&t)));
+ res = tdb_transaction_commit(cache_notrans);
+ if (res == -1) {
+ DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: "
+ "%s\n", tdb_errorstr(cache)));
+ return false;
+ }
- if (t <= time(NULL)) {
- /* We're expired */
- if (expired) {
- *expired = True;
- }
+ now = talloc_asprintf(talloc_tos(), "%d", (int)time(NULL));
+ if (now != NULL) {
+ tdb_store(cache_notrans, last_stabilize_key(),
+ string_term_tdb_data(now), 0);
+ TALLOC_FREE(now);
}
- if (blob) {
- *blob = data_blob(blob_buf, blob_len);
- if (!blob->data) {
- goto out;
+ return true;
+}
+
+static int stabilize_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val,
+ void *priv)
+{
+ struct stabilize_state *state = (struct stabilize_state *)priv;
+ int res;
+ time_t timeout;
+
+ if (tdb_data_cmp(key, last_stabilize_key()) == 0) {
+ return 0;
+ }
+
+ if (!gencache_pull_timeout((char *)val.dptr, &timeout, NULL)) {
+ DEBUG(10, ("Ignoring invalid entry\n"));
+ return 0;
+ }
+ if ((timeout < time(NULL)) || (val.dsize == 0)) {
+ res = tdb_delete(cache, key);
+ if ((res == -1) && (tdb_error(cache) == TDB_ERR_NOEXIST)) {
+ res = 0;
+ } else {
+ state->written = true;
+ }
+ } else {
+ res = tdb_store(cache, key, val, 0);
+ if (res == 0) {
+ state->written = true;
}
}
- ret = True;
- out:
- SAFE_FREE(blob_buf);
- SAFE_FREE(databuf.dptr);
+ if (res == -1) {
+ DEBUG(10, ("Transfer to gencache.tdb failed: %s\n",
+ tdb_errorstr(cache)));
+ state->error = true;
+ return -1;
+ }
- return ret;
+ if (tdb_delete(cache_notrans, key) == -1) {
+ DEBUG(10, ("tdb_delete from gencache_notrans.tdb failed: "
+ "%s\n", tdb_errorstr(cache_notrans)));
+ state->error = true;
+ return -1;
+ }
+ return 0;
}
/**
- * Set an entry in the cache file. If there's no such
- * one, then add it.
+ * Get existing entry from the cache file.
*
* @param keystr string that represents a key of this entry
- * @param blob DATA_BLOB value being cached
- * @param timeout time when the value is expired
+ * @param valstr buffer that is allocated and filled with the entry value
+ * buffer's disposing must be done outside
+ * @param timeout pointer to a time_t that is filled with entry's
+ * timeout
*
- * @retval true when entry is successfuly stored
- * @retval false on failure
+ * @retval true when entry is successfuly fetched
+ * @retval False for failure
**/
-bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob, time_t timeout)
+bool gencache_get(const char *keystr, char **value, time_t *ptimeout)
{
+ DATA_BLOB blob;
bool ret = False;
- int tdb_ret;
- TDB_DATA databuf;
- char *valstr = NULL;
- unsigned char *buf = NULL;
- int len = 0, buflen = 0;
- /* fail completely if get null pointers passed */
- SMB_ASSERT(keystr && blob);
-
- if (!gencache_init()) {
- return False;
+ ret = gencache_get_data_blob(keystr, &blob, ptimeout);
+ if (!ret) {
+ return false;
}
-
- if (asprintf(&valstr, "%12u/%s", (int)timeout, BLOB_TYPE) == -1) {
- return False;
+ if ((blob.data == NULL) || (blob.length == 0)) {
+ SAFE_FREE(blob.data);
+ return false;
}
-
- again:
- len = 0;
-
- len += tdb_pack(buf+len, buflen-len, "fB",
- valstr,
- blob->length, blob->data);
-
- if (len == -1) {
- goto out;
+ if (blob.data[blob.length-1] != '\0') {
+ /* Not NULL terminated, can't be a string */
+ SAFE_FREE(blob.data);
+ return false;
}
-
- if (buflen < len) {
- SAFE_FREE(buf);
- buf = SMB_MALLOC_ARRAY(unsigned char, len);
- if (!buf) {
- goto out;
- }
- buflen = len;
- goto again;
- }
-
- databuf = make_tdb_data(buf, len);
-
- DEBUG(10,("Adding cache entry with key = %s; "
- "blob size = %d and timeout = %s"
- "(%d seconds %s)\n", keystr, (int)databuf.dsize,
- ctime(&timeout), (int)(timeout - time(NULL)),
- timeout > time(NULL) ? "ahead" : "in the past"));
-
- tdb_ret = tdb_store_bystring(cache, keystr, databuf, 0);
- if (tdb_ret == 0) {
- ret = True;
+ *value = SMB_STRDUP((char *)blob.data);
+ data_blob_free(&blob);
+ if (*value == NULL) {
+ return false;
}
+ return true;
+}
- out:
- SAFE_FREE(valstr);
- SAFE_FREE(buf);
+/**
+ * Set an entry in the cache file. If there's no such
+ * one, then add it.
+ *
+ * @param keystr string that represents a key of this entry
+ * @param value text representation value being cached
+ * @param timeout time when the value is expired
+ *
+ * @retval true when entry is successfuly stored
+ * @retval false on failure
+ **/
- return ret;
+bool gencache_set(const char *keystr, const char *value, time_t timeout)
+{
+ DATA_BLOB blob = data_blob_const(value, strlen(value)+1);
+ return gencache_set_data_blob(keystr, &blob, timeout);
}
/**
@@ -401,6 +558,7 @@ struct gencache_iterate_state {
void *priv);
const char *pattern;
void *priv;
+ bool in_persistent;
};
static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key,
@@ -416,6 +574,14 @@ static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key,
time_t timeout;
char *timeout_endp;
+ if (tdb_data_cmp(key, last_stabilize_key()) == 0) {
+ return 0;
+ }
+
+ if (state->in_persistent && tdb_exists(cache_notrans, key)) {
+ return 0;
+ }
+
if (key.dptr[key.dsize-1] == '\0') {
keystr = (char *)key.dptr;
} else {
@@ -465,8 +631,9 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time
{
struct gencache_iterate_state state;
- /* fail completely if get null pointers passed */
- SMB_ASSERT(fn && keystr_pattern);
+ if ((fn == NULL) || (keystr_pattern == NULL)) {
+ return;
+ }
if (!gencache_init()) return;
@@ -475,30 +642,10 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time
state.fn = fn;
state.pattern = keystr_pattern;
state.priv = data;
- tdb_traverse(cache, gencache_iterate_fn, &state);
-}
-/********************************************************************
- lock a key
-********************************************************************/
+ state.in_persistent = false;
+ tdb_traverse(cache_notrans, gencache_iterate_fn, &state);
-int gencache_lock_entry( const char *key )
-{
- if (!gencache_init())
- return -1;
-
- return tdb_lock_bystring(cache, key);
-}
-
-/********************************************************************
- unlock a key
-********************************************************************/
-
-void gencache_unlock_entry( const char *key )
-{
- if (!gencache_init())
- return;
-
- tdb_unlock_bystring(cache, key);
- return;
+ state.in_persistent = true;
+ tdb_traverse(cache, gencache_iterate_fn, &state);
}
diff --git a/source3/lib/ldap_escape.c b/source3/lib/ldap_escape.c
index d101bc5ecd..a731cb9864 100644
--- a/source3/lib/ldap_escape.c
+++ b/source3/lib/ldap_escape.c
@@ -32,10 +32,10 @@
* and to be free()ed by the caller.
**/
-char *escape_ldap_string_alloc(const char *s)
+char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s)
{
size_t len = strlen(s)+1;
- char *output = (char *)SMB_MALLOC(len);
+ char *output = talloc_array(mem_ctx, char, len);
const char *sub;
int i = 0;
char *p = output;
@@ -43,7 +43,7 @@ char *escape_ldap_string_alloc(const char *s)
if (output == NULL) {
return NULL;
}
-
+
while (*s)
{
switch (*s)
@@ -64,14 +64,17 @@ char *escape_ldap_string_alloc(const char *s)
sub = NULL;
break;
}
-
+
if (sub) {
+ char *tmp;
len = len + 3;
- output = (char *)SMB_REALLOC(output, len);
- if (!output) {
+ tmp = talloc_realloc(mem_ctx, output, char, len);
+ if (tmp == NULL) {
+ TALLOC_FREE(output);
return NULL;
}
-
+ output = tmp;
+
p = &output[i];
strncpy (p, sub, 3);
p += 3;
@@ -84,7 +87,7 @@ char *escape_ldap_string_alloc(const char *s)
}
s++;
}
-
+
*p = '\0';
return output;
}
@@ -101,7 +104,7 @@ char *escape_rdn_val_string_alloc(const char *s)
}
p = output;
-
+
while (*s)
{
switch (*s)
@@ -122,10 +125,10 @@ char *escape_rdn_val_string_alloc(const char *s)
*p = *s;
p++;
}
-
+
s++;
}
-
+
*p = '\0';
/* resize the string to the actual final size */
diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c
index 2f8474b37f..e80879a1d2 100644
--- a/source3/lib/netapi/netapi.c
+++ b/source3/lib/netapi/netapi.c
@@ -170,7 +170,6 @@ NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
gfree_charcnv();
gfree_interfaces();
- gencache_shutdown();
secrets_shutdown();
TALLOC_FREE(ctx);
diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c
index 39472b20d7..9fa3ddd9a8 100644
--- a/source3/lib/netapi/user.c
+++ b/source3/lib/netapi/user.c
@@ -770,7 +770,7 @@ static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
{
uint32_t fl = UF_SCRIPT; /* god knows why */
- fl |= ads_acb2uf(acb);
+ fl |= ds_acb2uf(acb);
return fl;
}
diff --git a/source3/lib/smbldap_util.c b/source3/lib/smbldap_util.c
index 66aef6ba66..478a3d24ca 100644
--- a/source3/lib/smbldap_util.c
+++ b/source3/lib/smbldap_util.c
@@ -126,7 +126,7 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
char *escape_domain_name;
/* escape for filter */
- escape_domain_name = escape_ldap_string_alloc(domain_name);
+ escape_domain_name = escape_ldap_string(talloc_tos(), domain_name);
if (!escape_domain_name) {
DEBUG(0, ("Out of memory!\n"));
return NT_STATUS_NO_MEMORY;
@@ -135,11 +135,11 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
if (asprintf(&filter, "(&(%s=%s)(objectclass=%s))",
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
escape_domain_name, LDAP_OBJ_DOMINFO) < 0) {
- SAFE_FREE(escape_domain_name);
+ TALLOC_FREE(escape_domain_name);
return NT_STATUS_NO_MEMORY;
}
- SAFE_FREE(escape_domain_name);
+ TALLOC_FREE(escape_domain_name);
attr_list = get_attr_list(NULL, dominfo_attr_list );
rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
@@ -258,7 +258,7 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
int count;
char *escape_domain_name;
- escape_domain_name = escape_ldap_string_alloc(domain_name);
+ escape_domain_name = escape_ldap_string(talloc_tos(), domain_name);
if (!escape_domain_name) {
DEBUG(0, ("Out of memory!\n"));
return NT_STATUS_NO_MEMORY;
@@ -268,11 +268,11 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
LDAP_OBJ_DOMINFO,
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
escape_domain_name) < 0) {
- SAFE_FREE(escape_domain_name);
+ TALLOC_FREE(escape_domain_name);
return NT_STATUS_NO_MEMORY;
}
- SAFE_FREE(escape_domain_name);
+ TALLOC_FREE(escape_domain_name);
DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter));
diff --git a/source3/lib/system.c b/source3/lib/system.c
index ffc236e93b..6a4f5d5413 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -458,8 +458,6 @@ static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
static void get_create_timespec(const struct stat *pst, struct stat_ex *dst)
{
- struct timespec ret;
-
if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) {
dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
dst->st_ex_btime.tv_nsec = 0;
@@ -483,7 +481,7 @@ static void get_create_timespec(const struct stat *pst, struct stat_ex *dst)
/* Deal with systems that don't initialize birthtime correctly.
* Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
*/
- if (null_timespec(ret)) {
+ if (null_timespec(dst->st_ex_btime)) {
dst->st_ex_btime = calc_create_time_stat(pst);
dst->st_ex_calculated_birthtime = true;
}
diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index 451bc18d2e..fa56763a33 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -1618,7 +1618,7 @@ struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
static void tldap_add_done(struct tevent_req *subreq)
{
- return tldap_simple_done(subreq, TLDAP_RES_ADD);
+ tldap_simple_done(subreq, TLDAP_RES_ADD);
}
int tldap_add_recv(struct tevent_req *req)
@@ -1718,7 +1718,7 @@ struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
static void tldap_modify_done(struct tevent_req *subreq)
{
- return tldap_simple_done(subreq, TLDAP_RES_MODIFY);
+ tldap_simple_done(subreq, TLDAP_RES_MODIFY);
}
int tldap_modify_recv(struct tevent_req *req)
@@ -1795,7 +1795,7 @@ struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
static void tldap_delete_done(struct tevent_req *subreq)
{
- return tldap_simple_done(subreq, TLDAP_RES_DELETE);
+ tldap_simple_done(subreq, TLDAP_RES_DELETE);
}
int tldap_delete_recv(struct tevent_req *req)
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 31261afd72..af64f370ba 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -349,6 +349,9 @@ static const smb_socket_option socket_options[] = {
#ifdef TCP_FASTACK
{"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT},
#endif
+#ifdef TCP_QUICKACK
+ {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL},
+#endif
{NULL,0,0,0,0}};
/****************************************************************************
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index cdd7d0a300..c197fd7515 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -96,14 +96,14 @@ int StrCaseCmp(const char *s, const char *t)
return +1;
}
- if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
return strcmp(ps, pt);
/* Not quite the right answer, but finding the right one
under this failure case is expensive, and it's pretty
close */
}
- if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
TALLOC_FREE(buffer_s);
return strcmp(ps, pt);
/* Not quite the right answer, but finding the right one
@@ -157,14 +157,14 @@ int StrnCaseCmp(const char *s, const char *t, size_t len)
return 0;
}
- if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
return strncmp(ps, pt, len-n);
/* Not quite the right answer, but finding the right one
under this failure case is expensive,
and it's pretty close */
}
- if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
TALLOC_FREE(buffer_s);
return strncmp(ps, pt, len-n);
/* Not quite the right answer, but finding the right one
@@ -366,7 +366,7 @@ size_t str_charnum(const char *s)
{
size_t ret, converted_size;
smb_ucs2_t *tmpbuf2 = NULL;
- if (!push_ucs2_talloc(NULL, &tmpbuf2, s, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
return 0;
}
ret = strlen_w(tmpbuf2);
@@ -384,7 +384,7 @@ size_t str_ascii_charnum(const char *s)
{
size_t ret, converted_size;
char *tmpbuf2 = NULL;
- if (!push_ascii_talloc(NULL, &tmpbuf2, s, &converted_size)) {
+ if (!push_ascii_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
return 0;
}
ret = strlen(tmpbuf2);
@@ -455,7 +455,7 @@ bool strhasupper(const char *s)
bool ret;
size_t converted_size;
- if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) {
return false;
}
@@ -480,7 +480,7 @@ bool strhaslower(const char *s)
bool ret;
size_t converted_size;
- if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) {
return false;
}
@@ -1177,7 +1177,7 @@ char *strchr_m(const char *src, char c)
s = src;
#endif
- if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
/* Wrong answer, but what can we do... */
return strchr(src, c);
}
@@ -1187,7 +1187,7 @@ char *strchr_m(const char *src, char c)
return NULL;
}
*p = 0;
- if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) {
+ if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
SAFE_FREE(ws);
/* Wrong answer, but what can we do... */
return strchr(src, c);
@@ -1248,7 +1248,7 @@ char *strrchr_m(const char *s, char c)
char *ret;
size_t converted_size;
- if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
/* Wrong answer, but what can we do. */
return strrchr(s, c);
}
@@ -1258,7 +1258,7 @@ char *strrchr_m(const char *s, char c)
return NULL;
}
*p = 0;
- if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) {
+ if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
TALLOC_FREE(ws);
/* Wrong answer, but what can we do. */
return strrchr(s, c);
@@ -1283,7 +1283,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n)
char *ret;
size_t converted_size;
- if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
/* Too hard to try and get right. */
return NULL;
}
@@ -1293,7 +1293,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n)
return NULL;
}
*p = 0;
- if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) {
+ if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
TALLOC_FREE(ws);
/* Too hard to try and get right. */
return NULL;
@@ -1352,12 +1352,12 @@ char *strstr_m(const char *src, const char *findstr)
s = src;
#endif
- if (!push_ucs2_talloc(NULL, &src_w, src, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &src_w, src, &converted_size)) {
DEBUG(0,("strstr_m: src malloc fail\n"));
return NULL;
}
- if (!push_ucs2_talloc(NULL, &find_w, findstr, &converted_size)) {
+ if (!push_ucs2_talloc(talloc_tos(), &find_w, findstr, &converted_size)) {
TALLOC_FREE(src_w);
DEBUG(0,("strstr_m: find malloc fail\n"));
return NULL;
@@ -1372,7 +1372,7 @@ char *strstr_m(const char *src, const char *findstr)
}
*p = 0;
- if (!pull_ucs2_talloc(NULL, &s2, src_w, &converted_size)) {
+ if (!pull_ucs2_talloc(talloc_tos(), &s2, src_w, &converted_size)) {
TALLOC_FREE(src_w);
TALLOC_FREE(find_w);
DEBUG(0,("strstr_m: dest malloc fail\n"));
@@ -1932,7 +1932,7 @@ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */
SMB_ASSERT(result != NULL);
- while (len-- && out_cnt < (data.length * 2) - 5) {
+ while (len--) {
int c = (unsigned char) *(data.data++);
bits += c;
char_count++;
diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c
index 78fa7cd0a1..5b3d94dabe 100644
--- a/source3/lib/util_tdb.c
+++ b/source3/lib/util_tdb.c
@@ -630,3 +630,22 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err)
return NT_STATUS_INTERNAL_ERROR;
}
+
+int tdb_data_cmp(TDB_DATA t1, TDB_DATA t2)
+{
+ int ret;
+ if (t1.dptr == NULL && t2.dptr != NULL) {
+ return -1;
+ }
+ if (t1.dptr != NULL && t2.dptr == NULL) {
+ return 1;
+ }
+ if (t1.dptr == t2.dptr) {
+ return t1.dsize - t2.dsize;
+ }
+ ret = memcmp(t1.dptr, t2.dptr, MIN(t1.dsize, t2.dsize));
+ if (ret == 0) {
+ return t1.dsize - t2.dsize;
+ }
+ return ret;
+}